Fix warning and use of uninitialized variable.
[samba.git] / source3 / rpcclient / cmd_samr.c
1 /*
2    Unix SMB/CIFS implementation.
3    RPC pipe client
4
5    Copyright (C) Andrew Tridgell              1992-2000,
6    Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
7    Copyright (C) Elrond                            2000,
8    Copyright (C) Tim Potter                        2000
9
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 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%x ", 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%x ", 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%x ", 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 acct_info *dom_groups;
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_enum_dom_groups(
942                         cli, mem_ctx, &domain_pol, &start_idx, size,
943                         &dom_groups, &num_dom_groups);
944
945                 if (NT_STATUS_IS_OK(result) ||
946                     NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES)) {
947
948                         for (i = 0; i < num_dom_groups; i++)
949                                 printf("group:[%s] rid:[0x%x]\n",
950                                        dom_groups[i].acct_name,
951                                        dom_groups[i].rid);
952                 }
953
954         } while (NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES));
955
956  done:
957         if (got_domain_pol)
958                 rpccli_samr_Close(cli, mem_ctx, &domain_pol);
959
960         if (got_connect_pol)
961                 rpccli_samr_Close(cli, mem_ctx, &connect_pol);
962
963         return result;
964 }
965
966 /* Enumerate alias groups */
967
968 static NTSTATUS cmd_samr_enum_als_groups(struct rpc_pipe_client *cli,
969                                          TALLOC_CTX *mem_ctx,
970                                          int argc, const char **argv)
971 {
972         POLICY_HND connect_pol, domain_pol;
973         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
974         uint32 start_idx, size, num_als_groups, i;
975         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
976         struct acct_info *als_groups;
977         bool got_connect_pol = False, got_domain_pol = False;
978
979         if ((argc < 2) || (argc > 3)) {
980                 printf("Usage: %s builtin|domain [access mask]\n", argv[0]);
981                 return NT_STATUS_OK;
982         }
983
984         if (argc > 2)
985                 sscanf(argv[2], "%x", &access_mask);
986
987         /* Get sam policy handle */
988
989         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
990                                    &connect_pol);
991
992         if (!NT_STATUS_IS_OK(result))
993                 goto done;
994
995         got_connect_pol = True;
996
997         /* Get domain policy handle */
998
999         if (StrCaseCmp(argv[1], "domain")==0)
1000                 result = rpccli_samr_OpenDomain(cli, mem_ctx,
1001                                                 &connect_pol,
1002                                                 access_mask,
1003                                                 &domain_sid,
1004                                                 &domain_pol);
1005         else if (StrCaseCmp(argv[1], "builtin")==0)
1006                 result = rpccli_samr_OpenDomain(cli, mem_ctx,
1007                                                 &connect_pol,
1008                                                 access_mask,
1009                                                 CONST_DISCARD(struct dom_sid2 *, &global_sid_Builtin),
1010                                                 &domain_pol);
1011         else
1012                 return NT_STATUS_OK;
1013
1014         if (!NT_STATUS_IS_OK(result))
1015                 goto done;
1016
1017         got_domain_pol = True;
1018
1019         /* Enumerate alias groups */
1020
1021         start_idx = 0;
1022         size = 0xffff;          /* Number of groups to retrieve */
1023
1024         do {
1025                 result = rpccli_samr_enum_als_groups(
1026                         cli, mem_ctx, &domain_pol, &start_idx, size,
1027                         &als_groups, &num_als_groups);
1028
1029                 if (NT_STATUS_IS_OK(result) ||
1030                     NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES)) {
1031
1032                         for (i = 0; i < num_als_groups; i++)
1033                                 printf("group:[%s] rid:[0x%x]\n",
1034                                        als_groups[i].acct_name,
1035                                        als_groups[i].rid);
1036                 }
1037         } while (NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES));
1038
1039  done:
1040         if (got_domain_pol)
1041                 rpccli_samr_Close(cli, mem_ctx, &domain_pol);
1042
1043         if (got_connect_pol)
1044                 rpccli_samr_Close(cli, mem_ctx, &connect_pol);
1045
1046         return result;
1047 }
1048
1049 /* Query alias membership */
1050
1051 static NTSTATUS cmd_samr_query_aliasmem(struct rpc_pipe_client *cli,
1052                                         TALLOC_CTX *mem_ctx,
1053                                         int argc, const char **argv)
1054 {
1055         POLICY_HND connect_pol, domain_pol, alias_pol;
1056         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1057         uint32 alias_rid, i;
1058         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1059         struct lsa_SidArray sid_array;
1060
1061         if ((argc < 3) || (argc > 4)) {
1062                 printf("Usage: %s builtin|domain rid [access mask]\n", argv[0]);
1063                 return NT_STATUS_OK;
1064         }
1065
1066         sscanf(argv[2], "%i", &alias_rid);
1067
1068         if (argc > 3)
1069                 sscanf(argv[3], "%x", &access_mask);
1070
1071         /* Open SAMR handle */
1072
1073         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
1074                                    &connect_pol);
1075
1076         if (!NT_STATUS_IS_OK(result))
1077                 goto done;
1078
1079         /* Open handle on domain */
1080
1081         if (StrCaseCmp(argv[1], "domain")==0)
1082                 result = rpccli_samr_OpenDomain(cli, mem_ctx,
1083                                                 &connect_pol,
1084                                                 MAXIMUM_ALLOWED_ACCESS,
1085                                                 &domain_sid,
1086                                                 &domain_pol);
1087         else if (StrCaseCmp(argv[1], "builtin")==0)
1088                 result = rpccli_samr_OpenDomain(cli, mem_ctx,
1089                                                 &connect_pol,
1090                                                 MAXIMUM_ALLOWED_ACCESS,
1091                                                 CONST_DISCARD(struct dom_sid2 *, &global_sid_Builtin),
1092                                                 &domain_pol);
1093         else
1094                 return NT_STATUS_OK;
1095
1096         if (!NT_STATUS_IS_OK(result))
1097                 goto done;
1098
1099         /* Open handle on alias */
1100
1101         result = rpccli_samr_OpenAlias(cli, mem_ctx,
1102                                        &domain_pol,
1103                                        access_mask,
1104                                        alias_rid,
1105                                        &alias_pol);
1106         if (!NT_STATUS_IS_OK(result))
1107                 goto done;
1108
1109         result = rpccli_samr_GetMembersInAlias(cli, mem_ctx,
1110                                                &alias_pol,
1111                                                &sid_array);
1112
1113         if (!NT_STATUS_IS_OK(result))
1114                 goto done;
1115
1116         for (i = 0; i < sid_array.num_sids; i++) {
1117                 fstring sid_str;
1118
1119                 sid_to_fstring(sid_str, sid_array.sids[i].sid);
1120                 printf("\tsid:[%s]\n", sid_str);
1121         }
1122
1123         rpccli_samr_Close(cli, mem_ctx, &alias_pol);
1124         rpccli_samr_Close(cli, mem_ctx, &domain_pol);
1125         rpccli_samr_Close(cli, mem_ctx, &connect_pol);
1126  done:
1127         return result;
1128 }
1129
1130 /* Query alias info */
1131
1132 static NTSTATUS cmd_samr_query_aliasinfo(struct rpc_pipe_client *cli,
1133                                          TALLOC_CTX *mem_ctx,
1134                                          int argc, const char **argv)
1135 {
1136         POLICY_HND connect_pol, domain_pol, alias_pol;
1137         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1138         uint32_t alias_rid;
1139         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1140         union samr_AliasInfo *info = NULL;
1141         enum samr_AliasInfoEnum level = ALIASINFOALL;
1142
1143         if ((argc < 3) || (argc > 4)) {
1144                 printf("Usage: %s builtin|domain rid [level] [access mask]\n",
1145                         argv[0]);
1146                 return NT_STATUS_OK;
1147         }
1148
1149         sscanf(argv[2], "%i", &alias_rid);
1150
1151         if (argc > 3) {
1152                 level = atoi(argv[3]);
1153         }
1154
1155         if (argc > 4) {
1156                 sscanf(argv[4], "%x", &access_mask);
1157         }
1158
1159         /* Open SAMR handle */
1160
1161         result = try_samr_connects(cli, mem_ctx,
1162                                    SEC_FLAG_MAXIMUM_ALLOWED,
1163                                    &connect_pol);
1164
1165         if (!NT_STATUS_IS_OK(result)) {
1166                 goto done;
1167         }
1168
1169         /* Open handle on domain */
1170
1171         if (strequal(argv[1], "domain")) {
1172
1173                 result = rpccli_samr_OpenDomain(cli, mem_ctx,
1174                                                 &connect_pol,
1175                                                 SEC_FLAG_MAXIMUM_ALLOWED,
1176                                                 &domain_sid,
1177                                                 &domain_pol);
1178
1179         } else if (strequal(argv[1], "builtin")) {
1180
1181                 result = rpccli_samr_OpenDomain(cli, mem_ctx,
1182                                                 &connect_pol,
1183                                                 SEC_FLAG_MAXIMUM_ALLOWED,
1184                                                 CONST_DISCARD(struct dom_sid2 *, &global_sid_Builtin),
1185                                                 &domain_pol);
1186
1187         } else {
1188                 return NT_STATUS_OK;
1189         }
1190
1191         if (!NT_STATUS_IS_OK(result)) {
1192                 goto done;
1193         }
1194
1195         /* Open handle on alias */
1196
1197         result = rpccli_samr_OpenAlias(cli, mem_ctx,
1198                                        &domain_pol,
1199                                        access_mask,
1200                                        alias_rid,
1201                                        &alias_pol);
1202         if (!NT_STATUS_IS_OK(result)) {
1203                 goto done;
1204         }
1205
1206         result = rpccli_samr_QueryAliasInfo(cli, mem_ctx,
1207                                             &alias_pol,
1208                                             level,
1209                                             &info);
1210
1211         if (!NT_STATUS_IS_OK(result)) {
1212                 goto done;
1213         }
1214
1215         switch (level) {
1216                 case ALIASINFOALL:
1217                         printf("Name: %s\n", info->all.name.string);
1218                         printf("Description: %s\n", info->all.description.string);
1219                         printf("Num Members: %d\n", info->all.num_members);
1220                         break;
1221                 case ALIASINFONAME:
1222                         printf("Name: %s\n", info->name.string);
1223                         break;
1224                 case ALIASINFODESCRIPTION:
1225                         printf("Description: %s\n", info->description.string);
1226                         break;
1227                 default:
1228                         break;
1229         }
1230
1231         rpccli_samr_Close(cli, mem_ctx, &alias_pol);
1232         rpccli_samr_Close(cli, mem_ctx, &domain_pol);
1233         rpccli_samr_Close(cli, mem_ctx, &connect_pol);
1234  done:
1235         return result;
1236 }
1237
1238
1239 /* Query delete an alias membership */
1240
1241 static NTSTATUS cmd_samr_delete_alias(struct rpc_pipe_client *cli,
1242                                       TALLOC_CTX *mem_ctx,
1243                                       int argc, const char **argv)
1244 {
1245         POLICY_HND connect_pol, domain_pol, alias_pol;
1246         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1247         uint32 alias_rid;
1248         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1249
1250         if (argc != 3) {
1251                 printf("Usage: %s builtin|domain [rid|name]\n", argv[0]);
1252                 return NT_STATUS_OK;
1253         }
1254
1255         alias_rid = strtoul(argv[2], NULL, 10);
1256
1257         /* Open SAMR handle */
1258
1259         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
1260                                    &connect_pol);
1261
1262         if (!NT_STATUS_IS_OK(result))
1263                 goto done;
1264
1265         /* Open handle on domain */
1266
1267         if (StrCaseCmp(argv[1], "domain")==0)
1268                 result = rpccli_samr_OpenDomain(cli, mem_ctx,
1269                                                 &connect_pol,
1270                                                 MAXIMUM_ALLOWED_ACCESS,
1271                                                 &domain_sid,
1272                                                 &domain_pol);
1273         else if (StrCaseCmp(argv[1], "builtin")==0)
1274                 result = rpccli_samr_OpenDomain(cli, mem_ctx,
1275                                                 &connect_pol,
1276                                                 MAXIMUM_ALLOWED_ACCESS,
1277                                                 CONST_DISCARD(struct dom_sid2 *, &global_sid_Builtin),
1278                                                 &domain_pol);
1279         else
1280                 return NT_STATUS_INVALID_PARAMETER;
1281
1282         if (!NT_STATUS_IS_OK(result))
1283                 goto done;
1284
1285         /* Open handle on alias */
1286
1287         result = rpccli_samr_OpenAlias(cli, mem_ctx,
1288                                        &domain_pol,
1289                                        access_mask,
1290                                        alias_rid,
1291                                        &alias_pol);
1292         if (!NT_STATUS_IS_OK(result) && (alias_rid == 0)) {
1293                 /* Probably this was a user name, try lookupnames */
1294                 struct samr_Ids rids, types;
1295                 struct lsa_String lsa_acct_name;
1296
1297                 init_lsa_String(&lsa_acct_name, argv[2]);
1298
1299                 result = rpccli_samr_LookupNames(cli, mem_ctx,
1300                                                  &domain_pol,
1301                                                  1,
1302                                                  &lsa_acct_name,
1303                                                  &rids,
1304                                                  &types);
1305
1306                 if (NT_STATUS_IS_OK(result)) {
1307                         result = rpccli_samr_OpenAlias(cli, mem_ctx,
1308                                                        &domain_pol,
1309                                                        access_mask,
1310                                                        rids.ids[0],
1311                                                        &alias_pol);
1312                 }
1313         }
1314
1315         result = rpccli_samr_DeleteDomAlias(cli, mem_ctx,
1316                                             &alias_pol);
1317
1318         if (!NT_STATUS_IS_OK(result))
1319                 goto done;
1320
1321         rpccli_samr_Close(cli, mem_ctx, &domain_pol);
1322         rpccli_samr_Close(cli, mem_ctx, &connect_pol);
1323  done:
1324         return result;
1325 }
1326
1327 /* Query display info */
1328
1329 static NTSTATUS cmd_samr_query_dispinfo(struct rpc_pipe_client *cli,
1330                                         TALLOC_CTX *mem_ctx,
1331                                         int argc, const char **argv)
1332 {
1333         POLICY_HND connect_pol, domain_pol;
1334         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1335         uint32 start_idx=0, max_entries=250, max_size = 0xffff, num_entries = 0, i;
1336         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1337         uint32 info_level = 1;
1338         union samr_DispInfo info;
1339         int loop_count = 0;
1340         bool got_params = False; /* Use get_query_dispinfo_params() or not? */
1341         uint32_t total_size, returned_size;
1342
1343         if (argc > 6) {
1344                 printf("Usage: %s [info level] [start index] [max entries] [max size] [access mask]\n", argv[0]);
1345                 return NT_STATUS_OK;
1346         }
1347
1348         if (argc >= 2)
1349                 sscanf(argv[1], "%i", &info_level);
1350
1351         if (argc >= 3)
1352                 sscanf(argv[2], "%i", &start_idx);
1353
1354         if (argc >= 4) {
1355                 sscanf(argv[3], "%i", &max_entries);
1356                 got_params = True;
1357         }
1358
1359         if (argc >= 5) {
1360                 sscanf(argv[4], "%i", &max_size);
1361                 got_params = True;
1362         }
1363
1364         if (argc >= 6)
1365                 sscanf(argv[5], "%x", &access_mask);
1366
1367         /* Get sam policy handle */
1368
1369         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
1370                                    &connect_pol);
1371
1372         if (!NT_STATUS_IS_OK(result))
1373                 goto done;
1374
1375         /* Get domain policy handle */
1376
1377         result = rpccli_samr_OpenDomain(cli, mem_ctx,
1378                                         &connect_pol,
1379                                         access_mask,
1380                                         &domain_sid,
1381                                         &domain_pol);
1382
1383         if (!NT_STATUS_IS_OK(result))
1384                 goto done;
1385
1386         /* Query display info */
1387
1388         do {
1389
1390                 if (!got_params)
1391                         get_query_dispinfo_params(
1392                                 loop_count, &max_entries, &max_size);
1393
1394                 result = rpccli_samr_QueryDisplayInfo(cli, mem_ctx,
1395                                                       &domain_pol,
1396                                                       info_level,
1397                                                       start_idx,
1398                                                       max_entries,
1399                                                       max_size,
1400                                                       &total_size,
1401                                                       &returned_size,
1402                                                       &info);
1403
1404                 loop_count++;
1405
1406                 switch (info_level) {
1407                         case 1:
1408                                 num_entries = info.info1.count;
1409                                 break;
1410                         case 2:
1411                                 num_entries = info.info2.count;
1412                                 break;
1413                         case 3:
1414                                 num_entries = info.info3.count;
1415                                 break;
1416                         case 4:
1417                                 num_entries = info.info4.count;
1418                                 break;
1419                         case 5:
1420                                 num_entries = info.info5.count;
1421                                 break;
1422                         default:
1423                                 break;
1424                 }
1425
1426                 start_idx += num_entries;
1427
1428                 if (NT_STATUS_IS_ERR(result))
1429                         break;
1430
1431                 if (num_entries == 0)
1432                         break;
1433
1434                 for (i = 0; i < num_entries; i++) {
1435                         switch (info_level) {
1436                         case 1:
1437                                 display_sam_info_1(&info.info1.entries[i]);
1438                                 break;
1439                         case 2:
1440                                 display_sam_info_2(&info.info2.entries[i]);
1441                                 break;
1442                         case 3:
1443                                 display_sam_info_3(&info.info3.entries[i]);
1444                                 break;
1445                         case 4:
1446                                 display_sam_info_4(&info.info4.entries[i]);
1447                                 break;
1448                         case 5:
1449                                 display_sam_info_5(&info.info5.entries[i]);
1450                                 break;
1451                         }
1452                 }
1453         } while ( NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
1454
1455         rpccli_samr_Close(cli, mem_ctx, &domain_pol);
1456         rpccli_samr_Close(cli, mem_ctx, &connect_pol);
1457  done:
1458         return result;
1459 }
1460
1461 /* Query domain info */
1462
1463 static NTSTATUS cmd_samr_query_dominfo(struct rpc_pipe_client *cli,
1464                                        TALLOC_CTX *mem_ctx,
1465                                        int argc, const char **argv)
1466 {
1467         POLICY_HND connect_pol, domain_pol;
1468         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1469         uint32 switch_level = 2;
1470         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1471         union samr_DomainInfo *info = NULL;
1472
1473         if (argc > 3) {
1474                 printf("Usage: %s [info level] [access mask]\n", argv[0]);
1475                 return NT_STATUS_OK;
1476         }
1477
1478         if (argc > 1)
1479                 sscanf(argv[1], "%i", &switch_level);
1480
1481         if (argc > 2)
1482                 sscanf(argv[2], "%x", &access_mask);
1483
1484         /* Get sam policy handle */
1485
1486         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
1487                                    &connect_pol);
1488
1489         if (!NT_STATUS_IS_OK(result))
1490                 goto done;
1491
1492         /* Get domain policy handle */
1493
1494         result = rpccli_samr_OpenDomain(cli, mem_ctx,
1495                                         &connect_pol,
1496                                         access_mask,
1497                                         &domain_sid,
1498                                         &domain_pol);
1499
1500         if (!NT_STATUS_IS_OK(result))
1501                 goto done;
1502
1503         /* Query domain info */
1504
1505         result = rpccli_samr_QueryDomainInfo(cli, mem_ctx,
1506                                              &domain_pol,
1507                                              switch_level,
1508                                              &info);
1509
1510         if (!NT_STATUS_IS_OK(result))
1511                 goto done;
1512
1513         /* Display domain info */
1514
1515         switch (switch_level) {
1516         case 1:
1517                 display_sam_dom_info_1(&info->info1);
1518                 break;
1519         case 2:
1520                 display_sam_dom_info_2(&info->info2);
1521                 break;
1522         case 3:
1523                 display_sam_dom_info_3(&info->info3);
1524                 break;
1525         case 4:
1526                 display_sam_dom_info_4(&info->info4);
1527                 break;
1528         case 5:
1529                 display_sam_dom_info_5(&info->info5);
1530                 break;
1531         case 6:
1532                 display_sam_dom_info_6(&info->info6);
1533                 break;
1534         case 7:
1535                 display_sam_dom_info_7(&info->info7);
1536                 break;
1537         case 8:
1538                 display_sam_dom_info_8(&info->info8);
1539                 break;
1540         case 9:
1541                 display_sam_dom_info_9(&info->info9);
1542                 break;
1543         case 12:
1544                 display_sam_dom_info_12(&info->info12);
1545                 break;
1546         case 13:
1547                 display_sam_dom_info_13(&info->info13);
1548                 break;
1549
1550         default:
1551                 printf("cannot display domain info for switch value %d\n",
1552                        switch_level);
1553                 break;
1554         }
1555
1556  done:
1557
1558         rpccli_samr_Close(cli, mem_ctx, &domain_pol);
1559         rpccli_samr_Close(cli, mem_ctx, &connect_pol);
1560         return result;
1561 }
1562
1563 /* Create domain user */
1564
1565 static NTSTATUS cmd_samr_create_dom_user(struct rpc_pipe_client *cli,
1566                                          TALLOC_CTX *mem_ctx,
1567                                          int argc, const char **argv)
1568 {
1569         POLICY_HND connect_pol, domain_pol, user_pol;
1570         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1571         struct lsa_String acct_name;
1572         uint32 acb_info;
1573         uint32 acct_flags, user_rid;
1574         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1575         uint32_t access_granted = 0;
1576
1577         if ((argc < 2) || (argc > 3)) {
1578                 printf("Usage: %s username [access mask]\n", argv[0]);
1579                 return NT_STATUS_OK;
1580         }
1581
1582         init_lsa_String(&acct_name, argv[1]);
1583
1584         if (argc > 2)
1585                 sscanf(argv[2], "%x", &access_mask);
1586
1587         /* Get sam policy handle */
1588
1589         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
1590                                    &connect_pol);
1591
1592         if (!NT_STATUS_IS_OK(result))
1593                 goto done;
1594
1595         /* Get domain policy handle */
1596
1597         result = rpccli_samr_OpenDomain(cli, mem_ctx,
1598                                         &connect_pol,
1599                                         access_mask,
1600                                         &domain_sid,
1601                                         &domain_pol);
1602
1603         if (!NT_STATUS_IS_OK(result))
1604                 goto done;
1605
1606         /* Create domain user */
1607
1608         acb_info = ACB_NORMAL;
1609         acct_flags = SEC_GENERIC_READ | SEC_GENERIC_WRITE | SEC_GENERIC_EXECUTE |
1610                      SEC_STD_WRITE_DAC | SEC_STD_DELETE |
1611                      SAMR_USER_ACCESS_SET_PASSWORD |
1612                      SAMR_USER_ACCESS_GET_ATTRIBUTES |
1613                      SAMR_USER_ACCESS_SET_ATTRIBUTES;
1614
1615         result = rpccli_samr_CreateUser2(cli, mem_ctx,
1616                                          &domain_pol,
1617                                          &acct_name,
1618                                          acb_info,
1619                                          acct_flags,
1620                                          &user_pol,
1621                                          &access_granted,
1622                                          &user_rid);
1623
1624         if (!NT_STATUS_IS_OK(result))
1625                 goto done;
1626
1627         result = rpccli_samr_Close(cli, mem_ctx, &user_pol);
1628         if (!NT_STATUS_IS_OK(result)) goto done;
1629
1630         result = rpccli_samr_Close(cli, mem_ctx, &domain_pol);
1631         if (!NT_STATUS_IS_OK(result)) goto done;
1632
1633         result = rpccli_samr_Close(cli, mem_ctx, &connect_pol);
1634         if (!NT_STATUS_IS_OK(result)) goto done;
1635
1636  done:
1637         return result;
1638 }
1639
1640 /* Create domain group */
1641
1642 static NTSTATUS cmd_samr_create_dom_group(struct rpc_pipe_client *cli,
1643                                           TALLOC_CTX *mem_ctx,
1644                                           int argc, const char **argv)
1645 {
1646         POLICY_HND connect_pol, domain_pol, group_pol;
1647         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1648         struct lsa_String grp_name;
1649         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1650         uint32_t rid = 0;
1651
1652         if ((argc < 2) || (argc > 3)) {
1653                 printf("Usage: %s groupname [access mask]\n", argv[0]);
1654                 return NT_STATUS_OK;
1655         }
1656
1657         init_lsa_String(&grp_name, argv[1]);
1658
1659         if (argc > 2)
1660                 sscanf(argv[2], "%x", &access_mask);
1661
1662         /* Get sam policy handle */
1663
1664         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
1665                                    &connect_pol);
1666
1667         if (!NT_STATUS_IS_OK(result))
1668                 goto done;
1669
1670         /* Get domain policy handle */
1671
1672         result = rpccli_samr_OpenDomain(cli, mem_ctx,
1673                                         &connect_pol,
1674                                         access_mask,
1675                                         &domain_sid,
1676                                         &domain_pol);
1677
1678         if (!NT_STATUS_IS_OK(result))
1679                 goto done;
1680
1681         /* Create domain user */
1682         result = rpccli_samr_CreateDomainGroup(cli, mem_ctx,
1683                                                &domain_pol,
1684                                                &grp_name,
1685                                                MAXIMUM_ALLOWED_ACCESS,
1686                                                &group_pol,
1687                                                &rid);
1688
1689         if (!NT_STATUS_IS_OK(result))
1690                 goto done;
1691
1692         result = rpccli_samr_Close(cli, mem_ctx, &group_pol);
1693         if (!NT_STATUS_IS_OK(result)) goto done;
1694
1695         result = rpccli_samr_Close(cli, mem_ctx, &domain_pol);
1696         if (!NT_STATUS_IS_OK(result)) goto done;
1697
1698         result = rpccli_samr_Close(cli, mem_ctx, &connect_pol);
1699         if (!NT_STATUS_IS_OK(result)) goto done;
1700
1701  done:
1702         return result;
1703 }
1704
1705 /* Create domain alias */
1706
1707 static NTSTATUS cmd_samr_create_dom_alias(struct rpc_pipe_client *cli,
1708                                           TALLOC_CTX *mem_ctx,
1709                                           int argc, const char **argv)
1710 {
1711         POLICY_HND connect_pol, domain_pol, alias_pol;
1712         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1713         struct lsa_String alias_name;
1714         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1715         uint32_t rid = 0;
1716
1717         if ((argc < 2) || (argc > 3)) {
1718                 printf("Usage: %s aliasname [access mask]\n", argv[0]);
1719                 return NT_STATUS_OK;
1720         }
1721
1722         init_lsa_String(&alias_name, argv[1]);
1723
1724         if (argc > 2)
1725                 sscanf(argv[2], "%x", &access_mask);
1726
1727         /* Get sam policy handle */
1728
1729         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
1730                                    &connect_pol);
1731
1732         if (!NT_STATUS_IS_OK(result))
1733                 goto done;
1734
1735         /* Get domain policy handle */
1736
1737         result = rpccli_samr_OpenDomain(cli, mem_ctx,
1738                                         &connect_pol,
1739                                         access_mask,
1740                                         &domain_sid,
1741                                         &domain_pol);
1742
1743         if (!NT_STATUS_IS_OK(result))
1744                 goto done;
1745
1746         /* Create domain user */
1747
1748         result = rpccli_samr_CreateDomAlias(cli, mem_ctx,
1749                                             &domain_pol,
1750                                             &alias_name,
1751                                             MAXIMUM_ALLOWED_ACCESS,
1752                                             &alias_pol,
1753                                             &rid);
1754
1755         if (!NT_STATUS_IS_OK(result))
1756                 goto done;
1757
1758         result = rpccli_samr_Close(cli, mem_ctx, &alias_pol);
1759         if (!NT_STATUS_IS_OK(result)) goto done;
1760
1761         result = rpccli_samr_Close(cli, mem_ctx, &domain_pol);
1762         if (!NT_STATUS_IS_OK(result)) goto done;
1763
1764         result = rpccli_samr_Close(cli, mem_ctx, &connect_pol);
1765         if (!NT_STATUS_IS_OK(result)) goto done;
1766
1767  done:
1768         return result;
1769 }
1770
1771 /* Lookup sam names */
1772
1773 static NTSTATUS cmd_samr_lookup_names(struct rpc_pipe_client *cli,
1774                                       TALLOC_CTX *mem_ctx,
1775                                       int argc, const char **argv)
1776 {
1777         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1778         POLICY_HND connect_pol, domain_pol;
1779         uint32 num_names;
1780         struct samr_Ids rids, name_types;
1781         int i;
1782         struct lsa_String *names = NULL;;
1783
1784         if (argc < 3) {
1785                 printf("Usage: %s  domain|builtin name1 [name2 [name3] [...]]\n", argv[0]);
1786                 printf("check on the domain SID: S-1-5-21-x-y-z\n");
1787                 printf("or check on the builtin SID: S-1-5-32\n");
1788                 return NT_STATUS_OK;
1789         }
1790
1791         /* Get sam policy and domain handles */
1792
1793         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
1794                                    &connect_pol);
1795
1796         if (!NT_STATUS_IS_OK(result))
1797                 goto done;
1798
1799         if (StrCaseCmp(argv[1], "domain")==0)
1800                 result = rpccli_samr_OpenDomain(cli, mem_ctx,
1801                                                 &connect_pol,
1802                                                 MAXIMUM_ALLOWED_ACCESS,
1803                                                 &domain_sid,
1804                                                 &domain_pol);
1805         else if (StrCaseCmp(argv[1], "builtin")==0)
1806                 result = rpccli_samr_OpenDomain(cli, mem_ctx,
1807                                                 &connect_pol,
1808                                                 MAXIMUM_ALLOWED_ACCESS,
1809                                                 CONST_DISCARD(struct dom_sid2 *, &global_sid_Builtin),
1810                                                 &domain_pol);
1811         else
1812                 return NT_STATUS_OK;
1813
1814         if (!NT_STATUS_IS_OK(result))
1815                 goto done;
1816
1817         /* Look up names */
1818
1819         num_names = argc - 2;
1820
1821         if ((names = TALLOC_ARRAY(mem_ctx, struct lsa_String, num_names)) == NULL) {
1822                 rpccli_samr_Close(cli, mem_ctx, &domain_pol);
1823                 rpccli_samr_Close(cli, mem_ctx, &connect_pol);
1824                 result = NT_STATUS_NO_MEMORY;
1825                 goto done;
1826         }
1827
1828         for (i = 0; i < num_names; i++) {
1829                 init_lsa_String(&names[i], argv[i + 2]);
1830         }
1831
1832         result = rpccli_samr_LookupNames(cli, mem_ctx,
1833                                          &domain_pol,
1834                                          num_names,
1835                                          names,
1836                                          &rids,
1837                                          &name_types);
1838
1839         if (!NT_STATUS_IS_OK(result))
1840                 goto done;
1841
1842         /* Display results */
1843
1844         for (i = 0; i < num_names; i++)
1845                 printf("name %s: 0x%x (%d)\n", names[i].string, rids.ids[i],
1846                        name_types.ids[i]);
1847
1848         rpccli_samr_Close(cli, mem_ctx, &domain_pol);
1849         rpccli_samr_Close(cli, mem_ctx, &connect_pol);
1850  done:
1851         return result;
1852 }
1853
1854 /* Lookup sam rids */
1855
1856 static NTSTATUS cmd_samr_lookup_rids(struct rpc_pipe_client *cli,
1857                                      TALLOC_CTX *mem_ctx,
1858                                      int argc, const char **argv)
1859 {
1860         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1861         POLICY_HND connect_pol, domain_pol;
1862         uint32_t num_rids, *rids;
1863         struct lsa_Strings names;
1864         struct samr_Ids types;
1865
1866         int i;
1867
1868         if (argc < 3) {
1869                 printf("Usage: %s domain|builtin rid1 [rid2 [rid3] [...]]\n", argv[0]);
1870                 return NT_STATUS_OK;
1871         }
1872
1873         /* Get sam policy and domain handles */
1874
1875         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
1876                                    &connect_pol);
1877
1878         if (!NT_STATUS_IS_OK(result))
1879                 goto done;
1880
1881         if (StrCaseCmp(argv[1], "domain")==0)
1882                 result = rpccli_samr_OpenDomain(cli, mem_ctx,
1883                                                 &connect_pol,
1884                                                 MAXIMUM_ALLOWED_ACCESS,
1885                                                 &domain_sid,
1886                                                 &domain_pol);
1887         else if (StrCaseCmp(argv[1], "builtin")==0)
1888                 result = rpccli_samr_OpenDomain(cli, mem_ctx,
1889                                                 &connect_pol,
1890                                                 MAXIMUM_ALLOWED_ACCESS,
1891                                                 CONST_DISCARD(struct dom_sid2 *, &global_sid_Builtin),
1892                                                 &domain_pol);
1893         else
1894                 return NT_STATUS_OK;
1895
1896         if (!NT_STATUS_IS_OK(result))
1897                 goto done;
1898
1899         /* Look up rids */
1900
1901         num_rids = argc - 2;
1902
1903         if ((rids = TALLOC_ARRAY(mem_ctx, uint32, num_rids)) == NULL) {
1904                 rpccli_samr_Close(cli, mem_ctx, &domain_pol);
1905                 rpccli_samr_Close(cli, mem_ctx, &connect_pol);
1906                 result = NT_STATUS_NO_MEMORY;
1907                 goto done;
1908         }
1909
1910         for (i = 0; i < argc - 2; i++)
1911                 sscanf(argv[i + 2], "%i", &rids[i]);
1912
1913         result = rpccli_samr_LookupRids(cli, mem_ctx,
1914                                         &domain_pol,
1915                                         num_rids,
1916                                         rids,
1917                                         &names,
1918                                         &types);
1919
1920         if (!NT_STATUS_IS_OK(result) &&
1921             !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED))
1922                 goto done;
1923
1924         /* Display results */
1925
1926         for (i = 0; i < num_rids; i++) {
1927                 printf("rid 0x%x: %s (%d)\n",
1928                         rids[i], names.names[i].string, types.ids[i]);
1929         }
1930
1931         rpccli_samr_Close(cli, mem_ctx, &domain_pol);
1932         rpccli_samr_Close(cli, mem_ctx, &connect_pol);
1933  done:
1934         return result;
1935 }
1936
1937 /* Delete domain group */
1938
1939 static NTSTATUS cmd_samr_delete_dom_group(struct rpc_pipe_client *cli,
1940                                          TALLOC_CTX *mem_ctx,
1941                                          int argc, const char **argv)
1942 {
1943         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1944         POLICY_HND connect_pol, domain_pol, group_pol;
1945         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1946
1947         if ((argc < 2) || (argc > 3)) {
1948                 printf("Usage: %s groupname\n", argv[0]);
1949                 return NT_STATUS_OK;
1950         }
1951
1952         if (argc > 2)
1953                 sscanf(argv[2], "%x", &access_mask);
1954
1955         /* Get sam policy and domain handles */
1956
1957         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
1958                                    &connect_pol);
1959
1960         if (!NT_STATUS_IS_OK(result))
1961                 goto done;
1962
1963         result = rpccli_samr_OpenDomain(cli, mem_ctx,
1964                                         &connect_pol,
1965                                         MAXIMUM_ALLOWED_ACCESS,
1966                                         &domain_sid,
1967                                         &domain_pol);
1968
1969         if (!NT_STATUS_IS_OK(result))
1970                 goto done;
1971
1972         /* Get handle on group */
1973
1974         {
1975                 struct samr_Ids group_rids, name_types;
1976                 struct lsa_String lsa_acct_name;
1977
1978                 init_lsa_String(&lsa_acct_name, argv[1]);
1979
1980                 result = rpccli_samr_LookupNames(cli, mem_ctx,
1981                                                  &domain_pol,
1982                                                  1,
1983                                                  &lsa_acct_name,
1984                                                  &group_rids,
1985                                                  &name_types);
1986                 if (!NT_STATUS_IS_OK(result))
1987                         goto done;
1988
1989                 result = rpccli_samr_OpenGroup(cli, mem_ctx,
1990                                                &domain_pol,
1991                                                access_mask,
1992                                                group_rids.ids[0],
1993                                                &group_pol);
1994
1995                 if (!NT_STATUS_IS_OK(result))
1996                         goto done;
1997         }
1998
1999         /* Delete group */
2000
2001         result = rpccli_samr_DeleteDomainGroup(cli, mem_ctx,
2002                                                &group_pol);
2003
2004         if (!NT_STATUS_IS_OK(result))
2005                 goto done;
2006
2007         /* Display results */
2008
2009         rpccli_samr_Close(cli, mem_ctx, &group_pol);
2010         rpccli_samr_Close(cli, mem_ctx, &domain_pol);
2011         rpccli_samr_Close(cli, mem_ctx, &connect_pol);
2012
2013  done:
2014         return result;
2015 }
2016
2017 /* Delete domain user */
2018
2019 static NTSTATUS cmd_samr_delete_dom_user(struct rpc_pipe_client *cli,
2020                                          TALLOC_CTX *mem_ctx,
2021                                          int argc, const char **argv)
2022 {
2023         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2024         POLICY_HND connect_pol, domain_pol, user_pol;
2025         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
2026
2027         if ((argc < 2) || (argc > 3)) {
2028                 printf("Usage: %s username\n", argv[0]);
2029                 return NT_STATUS_OK;
2030         }
2031
2032         if (argc > 2)
2033                 sscanf(argv[2], "%x", &access_mask);
2034
2035         /* Get sam policy and domain handles */
2036
2037         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
2038                                    &connect_pol);
2039
2040         if (!NT_STATUS_IS_OK(result))
2041                 goto done;
2042
2043         result = rpccli_samr_OpenDomain(cli, mem_ctx,
2044                                         &connect_pol,
2045                                         MAXIMUM_ALLOWED_ACCESS,
2046                                         &domain_sid,
2047                                         &domain_pol);
2048
2049         if (!NT_STATUS_IS_OK(result))
2050                 goto done;
2051
2052         /* Get handle on user */
2053
2054         {
2055                 struct samr_Ids user_rids, name_types;
2056                 struct lsa_String lsa_acct_name;
2057
2058                 init_lsa_String(&lsa_acct_name, argv[1]);
2059
2060                 result = rpccli_samr_LookupNames(cli, mem_ctx,
2061                                                  &domain_pol,
2062                                                  1,
2063                                                  &lsa_acct_name,
2064                                                  &user_rids,
2065                                                  &name_types);
2066
2067                 if (!NT_STATUS_IS_OK(result))
2068                         goto done;
2069
2070                 result = rpccli_samr_OpenUser(cli, mem_ctx,
2071                                               &domain_pol,
2072                                               access_mask,
2073                                               user_rids.ids[0],
2074                                               &user_pol);
2075
2076                 if (!NT_STATUS_IS_OK(result))
2077                         goto done;
2078         }
2079
2080         /* Delete user */
2081
2082         result = rpccli_samr_DeleteUser(cli, mem_ctx,
2083                                         &user_pol);
2084
2085         if (!NT_STATUS_IS_OK(result))
2086                 goto done;
2087
2088         /* Display results */
2089
2090         rpccli_samr_Close(cli, mem_ctx, &user_pol);
2091         rpccli_samr_Close(cli, mem_ctx, &domain_pol);
2092         rpccli_samr_Close(cli, mem_ctx, &connect_pol);
2093
2094  done:
2095         return result;
2096 }
2097
2098 /**********************************************************************
2099  * Query user security object
2100  */
2101 static NTSTATUS cmd_samr_query_sec_obj(struct rpc_pipe_client *cli,
2102                                     TALLOC_CTX *mem_ctx,
2103                                     int argc, const char **argv)
2104 {
2105         POLICY_HND connect_pol, domain_pol, user_pol, *pol;
2106         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2107         uint32 sec_info = DACL_SECURITY_INFORMATION;
2108         fstring server;
2109         uint32 user_rid = 0;
2110         TALLOC_CTX *ctx = NULL;
2111         SEC_DESC_BUF *sec_desc_buf=NULL;
2112         bool domain = False;
2113
2114         ctx=talloc_init("cmd_samr_query_sec_obj");
2115
2116         if ((argc < 1) || (argc > 3)) {
2117                 printf("Usage: %s [rid|-d] [sec_info]\n", argv[0]);
2118                 printf("\tSpecify rid for security on user, -d for security on domain\n");
2119                 talloc_destroy(ctx);
2120                 return NT_STATUS_OK;
2121         }
2122
2123         if (argc > 1) {
2124                 if (strcmp(argv[1], "-d") == 0)
2125                         domain = True;
2126                 else
2127                         sscanf(argv[1], "%i", &user_rid);
2128         }
2129
2130         if (argc == 3) {
2131                 sec_info = atoi(argv[2]);
2132         }
2133
2134         slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost);
2135         strupper_m(server);
2136         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
2137                                    &connect_pol);
2138
2139         if (!NT_STATUS_IS_OK(result))
2140                 goto done;
2141
2142         if (domain || user_rid)
2143                 result = rpccli_samr_OpenDomain(cli, mem_ctx,
2144                                                 &connect_pol,
2145                                                 MAXIMUM_ALLOWED_ACCESS,
2146                                                 &domain_sid,
2147                                                 &domain_pol);
2148
2149         if (!NT_STATUS_IS_OK(result))
2150                 goto done;
2151
2152         if (user_rid)
2153                 result = rpccli_samr_OpenUser(cli, mem_ctx,
2154                                               &domain_pol,
2155                                               MAXIMUM_ALLOWED_ACCESS,
2156                                               user_rid,
2157                                               &user_pol);
2158
2159         if (!NT_STATUS_IS_OK(result))
2160                 goto done;
2161
2162         /* Pick which query pol to use */
2163
2164         pol = &connect_pol;
2165
2166         if (domain)
2167                 pol = &domain_pol;
2168
2169         if (user_rid)
2170                 pol = &user_pol;
2171
2172         /* Query SAM security object */
2173
2174         result = rpccli_samr_QuerySecurity(cli, mem_ctx,
2175                                            pol,
2176                                            sec_info,
2177                                            &sec_desc_buf);
2178
2179         if (!NT_STATUS_IS_OK(result))
2180                 goto done;
2181
2182         display_sec_desc(sec_desc_buf->sd);
2183
2184         rpccli_samr_Close(cli, mem_ctx, &user_pol);
2185         rpccli_samr_Close(cli, mem_ctx, &domain_pol);
2186         rpccli_samr_Close(cli, mem_ctx, &connect_pol);
2187 done:
2188         talloc_destroy(ctx);
2189         return result;
2190 }
2191
2192 static NTSTATUS cmd_samr_get_usrdom_pwinfo(struct rpc_pipe_client *cli,
2193                                            TALLOC_CTX *mem_ctx,
2194                                            int argc, const char **argv)
2195 {
2196         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2197         POLICY_HND connect_pol, domain_pol, user_pol;
2198         struct samr_PwInfo info;
2199         uint32_t rid;
2200
2201         if (argc != 2) {
2202                 printf("Usage: %s rid\n", argv[0]);
2203                 return NT_STATUS_OK;
2204         }
2205
2206         sscanf(argv[1], "%i", &rid);
2207
2208         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
2209                                    &connect_pol);
2210
2211         if (!NT_STATUS_IS_OK(result)) {
2212                 goto done;
2213         }
2214
2215         result = rpccli_samr_OpenDomain(cli, mem_ctx,
2216                                         &connect_pol,
2217                                         MAXIMUM_ALLOWED_ACCESS,
2218                                         &domain_sid,
2219                                         &domain_pol);
2220
2221         if (!NT_STATUS_IS_OK(result)) {
2222                 goto done;
2223         }
2224
2225         result = rpccli_samr_OpenUser(cli, mem_ctx,
2226                                       &domain_pol,
2227                                       MAXIMUM_ALLOWED_ACCESS,
2228                                       rid,
2229                                       &user_pol);
2230
2231         if (!NT_STATUS_IS_OK(result)) {
2232                 goto done;
2233         }
2234
2235         result = rpccli_samr_GetUserPwInfo(cli, mem_ctx, &user_pol, &info);
2236         if (NT_STATUS_IS_OK(result)) {
2237                 printf("min_password_length: %d\n", info.min_password_length);
2238                 printf("%s\n",
2239                         NDR_PRINT_STRUCT_STRING(mem_ctx,
2240                                 samr_PasswordProperties, &info.password_properties));
2241         }
2242
2243  done:
2244         rpccli_samr_Close(cli, mem_ctx, &user_pol);
2245         rpccli_samr_Close(cli, mem_ctx, &domain_pol);
2246         rpccli_samr_Close(cli, mem_ctx, &connect_pol);
2247
2248         return result;
2249 }
2250
2251 static NTSTATUS cmd_samr_get_dom_pwinfo(struct rpc_pipe_client *cli,
2252                                         TALLOC_CTX *mem_ctx,
2253                                         int argc, const char **argv)
2254 {
2255         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2256         struct lsa_String domain_name;
2257         struct samr_PwInfo info;
2258
2259         if (argc < 1 || argc > 3) {
2260                 printf("Usage: %s <domain>\n", argv[0]);
2261                 return NT_STATUS_OK;
2262         }
2263
2264         init_lsa_String(&domain_name, argv[1]);
2265
2266         result = rpccli_samr_GetDomPwInfo(cli, mem_ctx, &domain_name, &info);
2267
2268         if (NT_STATUS_IS_OK(result)) {
2269                 printf("min_password_length: %d\n", info.min_password_length);
2270                 display_password_properties(info.password_properties);
2271         }
2272
2273         return result;
2274 }
2275
2276 /* Look up domain name */
2277
2278 static NTSTATUS cmd_samr_lookup_domain(struct rpc_pipe_client *cli,
2279                                        TALLOC_CTX *mem_ctx,
2280                                        int argc, const char **argv)
2281 {
2282         POLICY_HND connect_pol, domain_pol;
2283         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2284         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
2285         fstring sid_string;
2286         struct lsa_String domain_name;
2287         DOM_SID *sid = NULL;
2288
2289         if (argc != 2) {
2290                 printf("Usage: %s domain_name\n", argv[0]);
2291                 return NT_STATUS_OK;
2292         }
2293
2294         init_lsa_String(&domain_name, argv[1]);
2295
2296         result = try_samr_connects(cli, mem_ctx, access_mask, &connect_pol);
2297
2298         if (!NT_STATUS_IS_OK(result))
2299                 goto done;
2300
2301         result = rpccli_samr_OpenDomain(cli, mem_ctx,
2302                                         &connect_pol,
2303                                         access_mask,
2304                                         &domain_sid,
2305                                         &domain_pol);
2306
2307         if (!NT_STATUS_IS_OK(result))
2308                 goto done;
2309
2310         result = rpccli_samr_LookupDomain(cli, mem_ctx,
2311                                           &connect_pol,
2312                                           &domain_name,
2313                                           &sid);
2314
2315         if (NT_STATUS_IS_OK(result)) {
2316                 sid_to_fstring(sid_string, sid);
2317                 printf("SAMR_LOOKUP_DOMAIN: Domain Name: %s Domain SID: %s\n",
2318                        argv[1], sid_string);
2319         }
2320
2321         rpccli_samr_Close(cli, mem_ctx, &domain_pol);
2322         rpccli_samr_Close(cli, mem_ctx, &connect_pol);
2323 done:
2324         return result;
2325 }
2326
2327 /* Change user password */
2328
2329 static NTSTATUS cmd_samr_chgpasswd2(struct rpc_pipe_client *cli,
2330                                     TALLOC_CTX *mem_ctx,
2331                                     int argc, const char **argv)
2332 {
2333         POLICY_HND connect_pol, domain_pol;
2334         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2335         const char *user, *oldpass, *newpass;
2336         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
2337
2338         if (argc < 3) {
2339                 printf("Usage: %s username oldpass newpass\n", argv[0]);
2340                 return NT_STATUS_INVALID_PARAMETER;
2341         }
2342
2343         user = argv[1];
2344         oldpass = argv[2];
2345         newpass = argv[3];
2346
2347         /* Get sam policy handle */
2348
2349         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
2350                                    &connect_pol);
2351
2352         if (!NT_STATUS_IS_OK(result))
2353                 goto done;
2354
2355         /* Get domain policy handle */
2356
2357         result = rpccli_samr_OpenDomain(cli, mem_ctx,
2358                                         &connect_pol,
2359                                         access_mask,
2360                                         &domain_sid,
2361                                         &domain_pol);
2362
2363         if (!NT_STATUS_IS_OK(result))
2364                 goto done;
2365
2366         /* Change user password */
2367         result = rpccli_samr_chgpasswd_user(cli, mem_ctx, user, newpass, oldpass);
2368
2369         if (!NT_STATUS_IS_OK(result))
2370                 goto done;
2371
2372         result = rpccli_samr_Close(cli, mem_ctx, &domain_pol);
2373         if (!NT_STATUS_IS_OK(result)) goto done;
2374
2375         result = rpccli_samr_Close(cli, mem_ctx, &connect_pol);
2376         if (!NT_STATUS_IS_OK(result)) goto done;
2377
2378  done:
2379         return result;
2380 }
2381
2382
2383 /* Change user password */
2384
2385 static NTSTATUS cmd_samr_chgpasswd3(struct rpc_pipe_client *cli,
2386                                     TALLOC_CTX *mem_ctx,
2387                                     int argc, const char **argv)
2388 {
2389         POLICY_HND connect_pol, domain_pol;
2390         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2391         const char *user, *oldpass, *newpass;
2392         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
2393         struct samr_DomInfo1 *info = NULL;
2394         struct samr_ChangeReject *reject = NULL;
2395
2396         if (argc < 3) {
2397                 printf("Usage: %s username oldpass newpass\n", argv[0]);
2398                 return NT_STATUS_INVALID_PARAMETER;
2399         }
2400
2401         user = argv[1];
2402         oldpass = argv[2];
2403         newpass = argv[3];
2404
2405         /* Get sam policy handle */
2406
2407         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
2408                                    &connect_pol);
2409
2410         if (!NT_STATUS_IS_OK(result))
2411                 goto done;
2412
2413         /* Get domain policy handle */
2414
2415         result = rpccli_samr_OpenDomain(cli, mem_ctx,
2416                                         &connect_pol,
2417                                         access_mask,
2418                                         &domain_sid,
2419                                         &domain_pol);
2420
2421         if (!NT_STATUS_IS_OK(result))
2422                 goto done;
2423
2424         /* Change user password */
2425         result = rpccli_samr_chgpasswd3(cli, mem_ctx,
2426                                         user,
2427                                         newpass,
2428                                         oldpass,
2429                                         &info,
2430                                         &reject);
2431
2432         if (NT_STATUS_EQUAL(result, NT_STATUS_PASSWORD_RESTRICTION)) {
2433
2434                 display_sam_dom_info_1(info);
2435
2436                 switch (reject->reason) {
2437                         case SAMR_REJECT_TOO_SHORT:
2438                                 d_printf("SAMR_REJECT_TOO_SHORT\n");
2439                                 break;
2440                         case SAMR_REJECT_IN_HISTORY:
2441                                 d_printf("SAMR_REJECT_IN_HISTORY\n");
2442                                 break;
2443                         case SAMR_REJECT_COMPLEXITY:
2444                                 d_printf("SAMR_REJECT_COMPLEXITY\n");
2445                                 break;
2446                         case SAMR_REJECT_OTHER:
2447                                 d_printf("SAMR_REJECT_OTHER\n");
2448                                 break;
2449                         default:
2450                                 d_printf("unknown reject reason: %d\n",
2451                                         reject->reason);
2452                                 break;
2453                 }
2454         }
2455
2456         if (!NT_STATUS_IS_OK(result))
2457                 goto done;
2458
2459         result = rpccli_samr_Close(cli, mem_ctx, &domain_pol);
2460         if (!NT_STATUS_IS_OK(result)) goto done;
2461
2462         result = rpccli_samr_Close(cli, mem_ctx, &connect_pol);
2463         if (!NT_STATUS_IS_OK(result)) goto done;
2464
2465  done:
2466         return result;
2467 }
2468
2469 /* List of commands exported by this module */
2470
2471 struct cmd_set samr_commands[] = {
2472
2473         { "SAMR" },
2474
2475         { "queryuser",  RPC_RTYPE_NTSTATUS, cmd_samr_query_user,                NULL, PI_SAMR, NULL,    "Query user info",         "" },
2476         { "querygroup",         RPC_RTYPE_NTSTATUS, cmd_samr_query_group,               NULL, PI_SAMR, NULL,    "Query group info",        "" },
2477         { "queryusergroups",    RPC_RTYPE_NTSTATUS, cmd_samr_query_usergroups,  NULL, PI_SAMR, NULL,    "Query user groups",       "" },
2478         { "queryuseraliases",   RPC_RTYPE_NTSTATUS, cmd_samr_query_useraliases,         NULL, PI_SAMR, NULL,    "Query user aliases",      "" },
2479         { "querygroupmem",      RPC_RTYPE_NTSTATUS, cmd_samr_query_groupmem,    NULL, PI_SAMR, NULL,    "Query group membership",  "" },
2480         { "queryaliasmem",      RPC_RTYPE_NTSTATUS, cmd_samr_query_aliasmem,    NULL, PI_SAMR, NULL,    "Query alias membership",  "" },
2481         { "queryaliasinfo",     RPC_RTYPE_NTSTATUS, cmd_samr_query_aliasinfo,   NULL, PI_SAMR, NULL,    "Query alias info",       "" },
2482         { "deletealias",        RPC_RTYPE_NTSTATUS, cmd_samr_delete_alias,      NULL, PI_SAMR, NULL,    "Delete an alias",  "" },
2483         { "querydispinfo",      RPC_RTYPE_NTSTATUS, cmd_samr_query_dispinfo,    NULL, PI_SAMR, NULL,    "Query display info",      "" },
2484         { "querydominfo",       RPC_RTYPE_NTSTATUS, cmd_samr_query_dominfo,     NULL, PI_SAMR, NULL,    "Query domain info",       "" },
2485         { "enumdomusers",      RPC_RTYPE_NTSTATUS, cmd_samr_enum_dom_users,       NULL, PI_SAMR, NULL,  "Enumerate domain users", "" },
2486         { "enumdomgroups",      RPC_RTYPE_NTSTATUS, cmd_samr_enum_dom_groups,       NULL, PI_SAMR, NULL,        "Enumerate domain groups", "" },
2487         { "enumalsgroups",      RPC_RTYPE_NTSTATUS, cmd_samr_enum_als_groups,       NULL, PI_SAMR, NULL,        "Enumerate alias groups",  "" },
2488
2489         { "createdomuser",      RPC_RTYPE_NTSTATUS, cmd_samr_create_dom_user,       NULL, PI_SAMR, NULL,        "Create domain user",      "" },
2490         { "createdomgroup",     RPC_RTYPE_NTSTATUS, cmd_samr_create_dom_group,      NULL, PI_SAMR, NULL,        "Create domain group",     "" },
2491         { "createdomalias",     RPC_RTYPE_NTSTATUS, cmd_samr_create_dom_alias,      NULL, PI_SAMR, NULL,        "Create domain alias",     "" },
2492         { "samlookupnames",     RPC_RTYPE_NTSTATUS, cmd_samr_lookup_names,          NULL, PI_SAMR, NULL,        "Look up names",           "" },
2493         { "samlookuprids",      RPC_RTYPE_NTSTATUS, cmd_samr_lookup_rids,           NULL, PI_SAMR, NULL,        "Look up names",           "" },
2494         { "deletedomgroup",     RPC_RTYPE_NTSTATUS, cmd_samr_delete_dom_group,      NULL, PI_SAMR, NULL,        "Delete domain group",     "" },
2495         { "deletedomuser",      RPC_RTYPE_NTSTATUS, cmd_samr_delete_dom_user,       NULL, PI_SAMR, NULL,        "Delete domain user",      "" },
2496         { "samquerysecobj",     RPC_RTYPE_NTSTATUS, cmd_samr_query_sec_obj,         NULL, PI_SAMR, NULL, "Query SAMR security object",   "" },
2497         { "getdompwinfo",       RPC_RTYPE_NTSTATUS, cmd_samr_get_dom_pwinfo,        NULL, PI_SAMR, NULL, "Retrieve domain password info", "" },
2498         { "getusrdompwinfo",    RPC_RTYPE_NTSTATUS, cmd_samr_get_usrdom_pwinfo,     NULL, PI_SAMR, NULL, "Retrieve user domain password info", "" },
2499
2500         { "lookupdomain",       RPC_RTYPE_NTSTATUS, cmd_samr_lookup_domain,         NULL, PI_SAMR, NULL, "Lookup Domain Name", "" },
2501         { "chgpasswd2",         RPC_RTYPE_NTSTATUS, cmd_samr_chgpasswd2,            NULL, PI_SAMR, NULL, "Change user password", "" },
2502         { "chgpasswd3",         RPC_RTYPE_NTSTATUS, cmd_samr_chgpasswd3,            NULL, PI_SAMR, NULL, "Change user password", "" },
2503         { NULL }
2504 };