s3-auth Change type of num_sids to uint32_t
[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    Copyright (C) Guenther Deschner                 2008
10
11    This program is free software; you can redistribute it and/or modify
12    it under the terms of the GNU General Public License as published by
13    the Free Software Foundation; either version 3 of the License, or
14    (at your option) any later version.
15
16    This program is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19    GNU General Public License for more details.
20
21    You should have received a copy of the GNU General Public License
22    along with this program.  If not, see <http://www.gnu.org/licenses/>.
23 */
24
25 #include "includes.h"
26 #include "rpcclient.h"
27 #include "../libcli/auth/libcli_auth.h"
28 #include "../librpc/gen_ndr/ndr_samr.h"
29 #include "../librpc/gen_ndr/cli_samr.h"
30 #include "rpc_client/cli_samr.h"
31 #include "rpc_client/init_samr.h"
32 #include "rpc_client/init_lsa.h"
33
34 extern struct dom_sid domain_sid;
35
36 /****************************************************************************
37  display samr_user_info_7 structure
38  ****************************************************************************/
39 static void display_samr_user_info_7(struct samr_UserInfo7 *r)
40 {
41         printf("\tUser Name   :\t%s\n", r->account_name.string);
42 }
43
44 /****************************************************************************
45  display samr_user_info_9 structure
46  ****************************************************************************/
47 static void display_samr_user_info_9(struct samr_UserInfo9 *r)
48 {
49         printf("\tPrimary group RID   :\tox%x\n", r->primary_gid);
50 }
51
52 /****************************************************************************
53  display samr_user_info_16 structure
54  ****************************************************************************/
55 static void display_samr_user_info_16(struct samr_UserInfo16 *r)
56 {
57         printf("\tAcct Flags   :\tox%x\n", r->acct_flags);
58 }
59
60 /****************************************************************************
61  display samr_user_info_20 structure
62  ****************************************************************************/
63 static void display_samr_user_info_20(struct samr_UserInfo20 *r)
64 {
65         printf("\tRemote Dial :\n");
66         dump_data(0, (uint8_t *)r->parameters.array, r->parameters.length*2);
67 }
68
69
70 /****************************************************************************
71  display samr_user_info_21 structure
72  ****************************************************************************/
73 static void display_samr_user_info_21(struct samr_UserInfo21 *r)
74 {
75         printf("\tUser Name   :\t%s\n", r->account_name.string);
76         printf("\tFull Name   :\t%s\n", r->full_name.string);
77         printf("\tHome Drive  :\t%s\n", r->home_directory.string);
78         printf("\tDir Drive   :\t%s\n", r->home_drive.string);
79         printf("\tProfile Path:\t%s\n", r->profile_path.string);
80         printf("\tLogon Script:\t%s\n", r->logon_script.string);
81         printf("\tDescription :\t%s\n", r->description.string);
82         printf("\tWorkstations:\t%s\n", r->workstations.string);
83         printf("\tComment     :\t%s\n", r->comment.string);
84         printf("\tRemote Dial :\n");
85         dump_data(0, (uint8_t *)r->parameters.array, r->parameters.length*2);
86
87         printf("\tLogon Time               :\t%s\n",
88                http_timestring(talloc_tos(), nt_time_to_unix(r->last_logon)));
89         printf("\tLogoff Time              :\t%s\n",
90                http_timestring(talloc_tos(), nt_time_to_unix(r->last_logoff)));
91         printf("\tKickoff Time             :\t%s\n",
92                http_timestring(talloc_tos(), nt_time_to_unix(r->acct_expiry)));
93         printf("\tPassword last set Time   :\t%s\n",
94                http_timestring(talloc_tos(), nt_time_to_unix(r->last_password_change)));
95         printf("\tPassword can change Time :\t%s\n",
96                http_timestring(talloc_tos(), nt_time_to_unix(r->allow_password_change)));
97         printf("\tPassword must change Time:\t%s\n",
98                http_timestring(talloc_tos(), nt_time_to_unix(r->force_password_change)));
99
100         printf("\tunknown_2[0..31]...\n"); /* user passwords? */
101
102         printf("\tuser_rid :\t0x%x\n"  , r->rid); /* User ID */
103         printf("\tgroup_rid:\t0x%x\n"  , r->primary_gid); /* Group ID */
104         printf("\tacb_info :\t0x%08x\n", r->acct_flags); /* Account Control Info */
105
106         printf("\tfields_present:\t0x%08x\n", r->fields_present); /* 0x00ff ffff */
107         printf("\tlogon_divs:\t%d\n", r->logon_hours.units_per_week); /* 0x0000 00a8 which is 168 which is num hrs in a week */
108         printf("\tbad_password_count:\t0x%08x\n", r->bad_password_count);
109         printf("\tlogon_count:\t0x%08x\n", r->logon_count);
110
111         printf("\tpadding1[0..7]...\n");
112
113         if (r->logon_hours.bits) {
114                 printf("\tlogon_hrs[0..%d]...\n", r->logon_hours.units_per_week/8);
115         }
116 }
117
118
119 static void display_password_properties(uint32_t password_properties)
120 {
121         printf("password_properties: 0x%08x\n", password_properties);
122
123         if (password_properties & DOMAIN_PASSWORD_COMPLEX)
124                 printf("\tDOMAIN_PASSWORD_COMPLEX\n");
125
126         if (password_properties & DOMAIN_PASSWORD_NO_ANON_CHANGE)
127                 printf("\tDOMAIN_PASSWORD_NO_ANON_CHANGE\n");
128
129         if (password_properties & DOMAIN_PASSWORD_NO_CLEAR_CHANGE)
130                 printf("\tDOMAIN_PASSWORD_NO_CLEAR_CHANGE\n");
131
132         if (password_properties & DOMAIN_PASSWORD_LOCKOUT_ADMINS)
133                 printf("\tDOMAIN_PASSWORD_LOCKOUT_ADMINS\n");
134
135         if (password_properties & DOMAIN_PASSWORD_STORE_CLEARTEXT)
136                 printf("\tDOMAIN_PASSWORD_STORE_CLEARTEXT\n");
137
138         if (password_properties & DOMAIN_REFUSE_PASSWORD_CHANGE)
139                 printf("\tDOMAIN_REFUSE_PASSWORD_CHANGE\n");
140 }
141
142 static void display_sam_dom_info_1(struct samr_DomInfo1 *info1)
143 {
144         printf("Minimum password length:\t\t\t%d\n",
145                 info1->min_password_length);
146         printf("Password uniqueness (remember x passwords):\t%d\n",
147                 info1->password_history_length);
148         display_password_properties(info1->password_properties);
149         printf("password expire in:\t\t\t\t%s\n",
150                 display_time(info1->max_password_age));
151         printf("Min password age (allow changing in x days):\t%s\n",
152                 display_time(info1->min_password_age));
153 }
154
155 static void display_sam_dom_info_2(struct samr_DomGeneralInformation *general)
156 {
157         printf("Domain:\t\t%s\n", general->domain_name.string);
158         printf("Server:\t\t%s\n", general->primary.string);
159         printf("Comment:\t%s\n", general->oem_information.string);
160
161         printf("Total Users:\t%d\n", general->num_users);
162         printf("Total Groups:\t%d\n", general->num_groups);
163         printf("Total Aliases:\t%d\n", general->num_aliases);
164
165         printf("Sequence No:\t%llu\n", (unsigned long long)general->sequence_num);
166
167         printf("Force Logoff:\t%d\n",
168                 (int)nt_time_to_unix_abs(&general->force_logoff_time));
169
170         printf("Domain Server State:\t0x%x\n", general->domain_server_state);
171         printf("Server Role:\t%s\n", server_role_str(general->role));
172         printf("Unknown 3:\t0x%x\n", general->unknown3);
173 }
174
175 static void display_sam_dom_info_3(struct samr_DomInfo3 *info3)
176 {
177         printf("Force Logoff:\t%d\n",
178                 (int)nt_time_to_unix_abs(&info3->force_logoff_time));
179 }
180
181 static void display_sam_dom_info_4(struct samr_DomOEMInformation *oem)
182 {
183         printf("Comment:\t%s\n", oem->oem_information.string);
184 }
185
186 static void display_sam_dom_info_5(struct samr_DomInfo5 *info5)
187 {
188         printf("Domain:\t\t%s\n", info5->domain_name.string);
189 }
190
191 static void display_sam_dom_info_6(struct samr_DomInfo6 *info6)
192 {
193         printf("Server:\t\t%s\n", info6->primary.string);
194 }
195
196 static void display_sam_dom_info_7(struct samr_DomInfo7 *info7)
197 {
198         printf("Server Role:\t%s\n", server_role_str(info7->role));
199 }
200
201 static void display_sam_dom_info_8(struct samr_DomInfo8 *info8)
202 {
203         printf("Sequence No:\t%llu\n", (unsigned long long)info8->sequence_num);
204         printf("Domain Create Time:\t%s\n",
205                 http_timestring(talloc_tos(), nt_time_to_unix(info8->domain_create_time)));
206 }
207
208 static void display_sam_dom_info_9(struct samr_DomInfo9 *info9)
209 {
210         printf("Domain Server State:\t0x%x\n", info9->domain_server_state);
211 }
212
213 static void display_sam_dom_info_12(struct samr_DomInfo12 *info12)
214 {
215         printf("Bad password lockout duration:               %s\n",
216                 display_time(info12->lockout_duration));
217         printf("Reset Lockout after:                         %s\n",
218                 display_time(info12->lockout_window));
219         printf("Lockout after bad attempts:                  %d\n",
220                 info12->lockout_threshold);
221 }
222
223 static void display_sam_dom_info_13(struct samr_DomInfo13 *info13)
224 {
225         printf("Sequence No:\t%llu\n", (unsigned long long)info13->sequence_num);
226         printf("Domain Create Time:\t%s\n",
227                 http_timestring(talloc_tos(), nt_time_to_unix(info13->domain_create_time)));
228         printf("Sequence No at last promotion:\t%llu\n",
229                 (unsigned long long)info13->modified_count_at_last_promotion);
230 }
231
232 static void display_sam_info_1(struct samr_DispEntryGeneral *r)
233 {
234         printf("index: 0x%x ", r->idx);
235         printf("RID: 0x%x ", r->rid);
236         printf("acb: 0x%08x ", r->acct_flags);
237         printf("Account: %s\t", r->account_name.string);
238         printf("Name: %s\t", r->full_name.string);
239         printf("Desc: %s\n", r->description.string);
240 }
241
242 static void display_sam_info_2(struct samr_DispEntryFull *r)
243 {
244         printf("index: 0x%x ", r->idx);
245         printf("RID: 0x%x ", r->rid);
246         printf("acb: 0x%08x ", r->acct_flags);
247         printf("Account: %s\t", r->account_name.string);
248         printf("Desc: %s\n", r->description.string);
249 }
250
251 static void display_sam_info_3(struct samr_DispEntryFullGroup *r)
252 {
253         printf("index: 0x%x ", r->idx);
254         printf("RID: 0x%x ", r->rid);
255         printf("acb: 0x%08x ", r->acct_flags);
256         printf("Account: %s\t", r->account_name.string);
257         printf("Desc: %s\n", r->description.string);
258 }
259
260 static void display_sam_info_4(struct samr_DispEntryAscii *r)
261 {
262         printf("index: 0x%x ", r->idx);
263         printf("Account: %s\n", r->account_name.string);
264 }
265
266 static void display_sam_info_5(struct samr_DispEntryAscii *r)
267 {
268         printf("index: 0x%x ", r->idx);
269         printf("Account: %s\n", r->account_name.string);
270 }
271
272 /****************************************************************************
273  ****************************************************************************/
274
275 static NTSTATUS get_domain_handle(struct rpc_pipe_client *cli,
276                                   TALLOC_CTX *mem_ctx,
277                                   const char *sam,
278                                   struct policy_handle *connect_pol,
279                                   uint32_t access_mask,
280                                   struct dom_sid *_domain_sid,
281                                   struct policy_handle *domain_pol)
282 {
283
284         if (StrCaseCmp(sam, "domain") == 0) {
285                 return rpccli_samr_OpenDomain(cli, mem_ctx,
286                                               connect_pol,
287                                               access_mask,
288                                               _domain_sid,
289                                               domain_pol);
290         } else if (StrCaseCmp(sam, "builtin") == 0) {
291                 return rpccli_samr_OpenDomain(cli, mem_ctx,
292                                               connect_pol,
293                                               access_mask,
294                                               CONST_DISCARD(struct dom_sid2 *, &global_sid_Builtin),
295                                               domain_pol);
296         }
297
298         return NT_STATUS_INVALID_PARAMETER;
299 }
300
301 /**********************************************************************
302  * Query user information
303  */
304 static NTSTATUS cmd_samr_query_user(struct rpc_pipe_client *cli,
305                                     TALLOC_CTX *mem_ctx,
306                                     int argc, const char **argv)
307 {
308         struct policy_handle connect_pol, domain_pol, user_pol;
309         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
310         uint32 info_level = 21;
311         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
312         union samr_UserInfo *info = NULL;
313         uint32 user_rid = 0;
314
315         if ((argc < 2) || (argc > 4)) {
316                 printf("Usage: %s rid [info level] [access mask] \n", argv[0]);
317                 return NT_STATUS_OK;
318         }
319
320         sscanf(argv[1], "%i", &user_rid);
321
322         if (argc > 2)
323                 sscanf(argv[2], "%i", &info_level);
324
325         if (argc > 3)
326                 sscanf(argv[3], "%x", &access_mask);
327
328
329         result = rpccli_try_samr_connects(cli, mem_ctx,
330                                           MAXIMUM_ALLOWED_ACCESS,
331                                           &connect_pol);
332
333         if (!NT_STATUS_IS_OK(result))
334                 goto done;
335
336         result = rpccli_samr_OpenDomain(cli, mem_ctx,
337                                         &connect_pol,
338                                         MAXIMUM_ALLOWED_ACCESS,
339                                         &domain_sid,
340                                         &domain_pol);
341         if (!NT_STATUS_IS_OK(result))
342                 goto done;
343
344         result = rpccli_samr_OpenUser(cli, mem_ctx,
345                                       &domain_pol,
346                                       access_mask,
347                                       user_rid,
348                                       &user_pol);
349
350         if (NT_STATUS_EQUAL(result, NT_STATUS_NO_SUCH_USER) &&
351             (user_rid == 0)) {
352
353                 /* Probably this was a user name, try lookupnames */
354                 struct samr_Ids rids, types;
355                 struct lsa_String lsa_acct_name;
356
357                 init_lsa_String(&lsa_acct_name, argv[1]);
358
359                 result = rpccli_samr_LookupNames(cli, mem_ctx,
360                                                  &domain_pol,
361                                                  1,
362                                                  &lsa_acct_name,
363                                                  &rids,
364                                                  &types);
365
366                 if (NT_STATUS_IS_OK(result)) {
367                         result = rpccli_samr_OpenUser(cli, mem_ctx,
368                                                       &domain_pol,
369                                                       access_mask,
370                                                       rids.ids[0],
371                                                       &user_pol);
372                 }
373         }
374
375
376         if (!NT_STATUS_IS_OK(result))
377                 goto done;
378
379         result = rpccli_samr_QueryUserInfo(cli, mem_ctx,
380                                            &user_pol,
381                                            info_level,
382                                            &info);
383
384         if (!NT_STATUS_IS_OK(result))
385                 goto done;
386
387         switch (info_level) {
388         case 7:
389                 display_samr_user_info_7(&info->info7);
390                 break;
391         case 9:
392                 display_samr_user_info_9(&info->info9);
393                 break;
394         case 16:
395                 display_samr_user_info_16(&info->info16);
396                 break;
397         case 20:
398                 display_samr_user_info_20(&info->info20);
399                 break;
400         case 21:
401                 display_samr_user_info_21(&info->info21);
402                 break;
403         default:
404                 printf("Unsupported infolevel: %d\n", info_level);
405                 break;
406         }
407
408         rpccli_samr_Close(cli, mem_ctx, &user_pol);
409         rpccli_samr_Close(cli, mem_ctx, &domain_pol);
410         rpccli_samr_Close(cli, mem_ctx, &connect_pol);
411
412 done:
413         return result;
414 }
415
416 /****************************************************************************
417  display group info
418  ****************************************************************************/
419 static void display_group_info1(struct samr_GroupInfoAll *info1)
420 {
421         printf("\tGroup Name:\t%s\n", info1->name.string);
422         printf("\tDescription:\t%s\n", info1->description.string);
423         printf("\tGroup Attribute:%d\n", info1->attributes);
424         printf("\tNum Members:%d\n", info1->num_members);
425 }
426
427 /****************************************************************************
428  display group info
429  ****************************************************************************/
430 static void display_group_info2(struct lsa_String *info2)
431 {
432         printf("\tGroup Description:%s\n", info2->string);
433 }
434
435
436 /****************************************************************************
437  display group info
438  ****************************************************************************/
439 static void display_group_info3(struct samr_GroupInfoAttributes *info3)
440 {
441         printf("\tGroup Attribute:%d\n", info3->attributes);
442 }
443
444
445 /****************************************************************************
446  display group info
447  ****************************************************************************/
448 static void display_group_info4(struct lsa_String *info4)
449 {
450         printf("\tGroup Description:%s\n", info4->string);
451 }
452
453 /****************************************************************************
454  display group info
455  ****************************************************************************/
456 static void display_group_info5(struct samr_GroupInfoAll *info5)
457 {
458         printf("\tGroup Name:\t%s\n", info5->name.string);
459         printf("\tDescription:\t%s\n", info5->description.string);
460         printf("\tGroup Attribute:%d\n", info5->attributes);
461         printf("\tNum Members:%d\n", info5->num_members);
462 }
463
464 /****************************************************************************
465  display sam sync structure
466  ****************************************************************************/
467 static void display_group_info(union samr_GroupInfo *info,
468                                enum samr_GroupInfoEnum level)
469 {
470         switch (level) {
471                 case 1:
472                         display_group_info1(&info->all);
473                         break;
474                 case 2:
475                         display_group_info2(&info->name);
476                         break;
477                 case 3:
478                         display_group_info3(&info->attributes);
479                         break;
480                 case 4:
481                         display_group_info4(&info->description);
482                         break;
483                 case 5:
484                         display_group_info5(&info->all2);
485                         break;
486         }
487 }
488
489 /***********************************************************************
490  * Query group information
491  */
492 static NTSTATUS cmd_samr_query_group(struct rpc_pipe_client *cli,
493                                      TALLOC_CTX *mem_ctx,
494                                      int argc, const char **argv)
495 {
496         struct policy_handle connect_pol, domain_pol, group_pol;
497         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
498         enum samr_GroupInfoEnum info_level = GROUPINFOALL;
499         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
500         union samr_GroupInfo *group_info = NULL;
501         uint32 group_rid;
502
503         if ((argc < 2) || (argc > 4)) {
504                 printf("Usage: %s rid [info level] [access mask]\n", argv[0]);
505                 return NT_STATUS_OK;
506         }
507
508         sscanf(argv[1], "%i", &group_rid);
509
510         if (argc > 2)
511                 info_level = atoi(argv[2]);
512
513         if (argc > 3)
514                 sscanf(argv[3], "%x", &access_mask);
515
516         result = rpccli_try_samr_connects(cli, mem_ctx,
517                                           MAXIMUM_ALLOWED_ACCESS,
518                                           &connect_pol);
519
520         if (!NT_STATUS_IS_OK(result))
521                 goto done;
522
523         result = rpccli_samr_OpenDomain(cli, mem_ctx,
524                                         &connect_pol,
525                                         MAXIMUM_ALLOWED_ACCESS,
526                                         &domain_sid,
527                                         &domain_pol);
528
529         if (!NT_STATUS_IS_OK(result))
530                 goto done;
531
532         result = rpccli_samr_OpenGroup(cli, mem_ctx,
533                                        &domain_pol,
534                                        access_mask,
535                                        group_rid,
536                                        &group_pol);
537
538         if (!NT_STATUS_IS_OK(result))
539                 goto done;
540
541         result = rpccli_samr_QueryGroupInfo(cli, mem_ctx,
542                                             &group_pol,
543                                             info_level,
544                                             &group_info);
545         if (!NT_STATUS_IS_OK(result)) {
546                 goto done;
547         }
548
549         display_group_info(group_info, info_level);
550
551         rpccli_samr_Close(cli, mem_ctx, &group_pol);
552         rpccli_samr_Close(cli, mem_ctx, &domain_pol);
553         rpccli_samr_Close(cli, mem_ctx, &connect_pol);
554 done:
555         return result;
556 }
557
558 /* Query groups a user is a member of */
559
560 static NTSTATUS cmd_samr_query_usergroups(struct rpc_pipe_client *cli,
561                                           TALLOC_CTX *mem_ctx,
562                                           int argc, const char **argv)
563 {
564         struct policy_handle            connect_pol,
565                                 domain_pol,
566                                 user_pol;
567         NTSTATUS                result = NT_STATUS_UNSUCCESSFUL;
568         uint32                  user_rid;
569         uint32                  access_mask = MAXIMUM_ALLOWED_ACCESS;
570         int                     i;
571         struct samr_RidWithAttributeArray *rid_array = NULL;
572
573         if ((argc < 2) || (argc > 3)) {
574                 printf("Usage: %s rid [access mask]\n", argv[0]);
575                 return NT_STATUS_OK;
576         }
577
578         sscanf(argv[1], "%i", &user_rid);
579
580         if (argc > 2)
581                 sscanf(argv[2], "%x", &access_mask);
582
583         result = rpccli_try_samr_connects(cli, mem_ctx,
584                                           MAXIMUM_ALLOWED_ACCESS,
585                                           &connect_pol);
586
587         if (!NT_STATUS_IS_OK(result))
588                 goto done;
589
590         result = rpccli_samr_OpenDomain(cli, mem_ctx,
591                                         &connect_pol,
592                                         MAXIMUM_ALLOWED_ACCESS,
593                                         &domain_sid, &domain_pol);
594
595         if (!NT_STATUS_IS_OK(result))
596                 goto done;
597
598         result = rpccli_samr_OpenUser(cli, mem_ctx,
599                                       &domain_pol,
600                                       access_mask,
601                                       user_rid,
602                                       &user_pol);
603
604         if (!NT_STATUS_IS_OK(result))
605                 goto done;
606
607         result = rpccli_samr_GetGroupsForUser(cli, mem_ctx,
608                                               &user_pol,
609                                               &rid_array);
610
611         if (!NT_STATUS_IS_OK(result))
612                 goto done;
613
614         for (i = 0; i < rid_array->count; i++) {
615                 printf("\tgroup rid:[0x%x] attr:[0x%x]\n",
616                        rid_array->rids[i].rid,
617                        rid_array->rids[i].attributes);
618         }
619
620         rpccli_samr_Close(cli, mem_ctx, &user_pol);
621         rpccli_samr_Close(cli, mem_ctx, &domain_pol);
622         rpccli_samr_Close(cli, mem_ctx, &connect_pol);
623  done:
624         return result;
625 }
626
627 /* Query aliases a user is a member of */
628
629 static NTSTATUS cmd_samr_query_useraliases(struct rpc_pipe_client *cli,
630                                            TALLOC_CTX *mem_ctx,
631                                            int argc, const char **argv)
632 {
633         struct policy_handle            connect_pol, domain_pol;
634         NTSTATUS                result = NT_STATUS_UNSUCCESSFUL;
635         struct dom_sid                *sids;
636         uint32_t                     num_sids;
637         uint32                  access_mask = MAXIMUM_ALLOWED_ACCESS;
638         int                     i;
639         struct lsa_SidArray sid_array;
640         struct samr_Ids alias_rids;
641
642         if (argc < 3) {
643                 printf("Usage: %s builtin|domain sid1 sid2 ...\n", argv[0]);
644                 return NT_STATUS_INVALID_PARAMETER;
645         }
646
647         sids = NULL;
648         num_sids = 0;
649
650         for (i=2; i<argc; i++) {
651                 struct dom_sid tmp_sid;
652                 if (!string_to_sid(&tmp_sid, argv[i])) {
653                         printf("%s is not a legal SID\n", argv[i]);
654                         return NT_STATUS_INVALID_PARAMETER;
655                 }
656                 result = add_sid_to_array(mem_ctx, &tmp_sid, &sids, &num_sids);
657                 if (!NT_STATUS_IS_OK(result)) {
658                         return result;
659                 }
660         }
661
662         if (num_sids) {
663                 sid_array.sids = TALLOC_ZERO_ARRAY(mem_ctx, struct lsa_SidPtr, num_sids);
664                 if (sid_array.sids == NULL)
665                         return NT_STATUS_NO_MEMORY;
666         } else {
667                 sid_array.sids = NULL;
668         }
669
670         for (i=0; i<num_sids; i++) {
671                 sid_array.sids[i].sid = sid_dup_talloc(mem_ctx, &sids[i]);
672                 if (!sid_array.sids[i].sid) {
673                         return NT_STATUS_NO_MEMORY;
674                 }
675         }
676
677         sid_array.num_sids = num_sids;
678
679         result = rpccli_try_samr_connects(cli, mem_ctx,
680                                           MAXIMUM_ALLOWED_ACCESS,
681                                           &connect_pol);
682
683         if (!NT_STATUS_IS_OK(result))
684                 goto done;
685
686         result = get_domain_handle(cli, mem_ctx, argv[1],
687                                    &connect_pol,
688                                    access_mask,
689                                    &domain_sid,
690                                    &domain_pol);
691
692         if (!NT_STATUS_IS_OK(result))
693                 goto done;
694
695         result = rpccli_samr_GetAliasMembership(cli, mem_ctx,
696                                                 &domain_pol,
697                                                 &sid_array,
698                                                 &alias_rids);
699         if (!NT_STATUS_IS_OK(result))
700                 goto done;
701
702         for (i = 0; i < alias_rids.count; i++) {
703                 printf("\tgroup rid:[0x%x]\n", alias_rids.ids[i]);
704         }
705
706         rpccli_samr_Close(cli, mem_ctx, &domain_pol);
707         rpccli_samr_Close(cli, mem_ctx, &connect_pol);
708  done:
709         return result;
710 }
711
712 /* Query members of a group */
713
714 static NTSTATUS cmd_samr_query_groupmem(struct rpc_pipe_client *cli,
715                                         TALLOC_CTX *mem_ctx,
716                                         int argc, const char **argv)
717 {
718         struct policy_handle connect_pol, domain_pol, group_pol;
719         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
720         uint32 group_rid;
721         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
722         int i;
723         unsigned int old_timeout;
724         struct samr_RidTypeArray *rids = NULL;
725
726         if ((argc < 2) || (argc > 3)) {
727                 printf("Usage: %s rid [access mask]\n", argv[0]);
728                 return NT_STATUS_OK;
729         }
730
731         sscanf(argv[1], "%i", &group_rid);
732
733         if (argc > 2)
734                 sscanf(argv[2], "%x", &access_mask);
735
736         result = rpccli_try_samr_connects(cli, mem_ctx,
737                                           MAXIMUM_ALLOWED_ACCESS,
738                                           &connect_pol);
739
740         if (!NT_STATUS_IS_OK(result))
741                 goto done;
742
743         result = rpccli_samr_OpenDomain(cli, mem_ctx,
744                                         &connect_pol,
745                                         MAXIMUM_ALLOWED_ACCESS,
746                                         &domain_sid,
747                                         &domain_pol);
748
749         if (!NT_STATUS_IS_OK(result))
750                 goto done;
751
752         result = rpccli_samr_OpenGroup(cli, mem_ctx,
753                                        &domain_pol,
754                                        access_mask,
755                                        group_rid,
756                                        &group_pol);
757
758         if (!NT_STATUS_IS_OK(result))
759                 goto done;
760
761         /* Make sure to wait for our DC's reply */
762         old_timeout = rpccli_set_timeout(cli, 30000); /* 30 seconds. */
763         rpccli_set_timeout(cli, MAX(30000, old_timeout)); /* At least 30 sec */
764
765         result = rpccli_samr_QueryGroupMember(cli, mem_ctx,
766                                               &group_pol,
767                                               &rids);
768
769         rpccli_set_timeout(cli, old_timeout);
770
771         if (!NT_STATUS_IS_OK(result))
772                 goto done;
773
774         for (i = 0; i < rids->count; i++) {
775                 printf("\trid:[0x%x] attr:[0x%x]\n", rids->rids[i],
776                        rids->types[i]);
777         }
778
779         rpccli_samr_Close(cli, mem_ctx, &group_pol);
780         rpccli_samr_Close(cli, mem_ctx, &domain_pol);
781         rpccli_samr_Close(cli, mem_ctx, &connect_pol);
782  done:
783         return result;
784 }
785
786 /* Enumerate domain users */
787
788 static NTSTATUS cmd_samr_enum_dom_users(struct rpc_pipe_client *cli,
789                                         TALLOC_CTX *mem_ctx,
790                                         int argc, const char **argv)
791 {
792         struct policy_handle connect_pol, domain_pol;
793         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
794         uint32 start_idx, num_dom_users, i;
795         struct samr_SamArray *dom_users = NULL;
796         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
797         uint32 acb_mask = ACB_NORMAL;
798         uint32_t size = 0xffff;
799
800         if ((argc < 1) || (argc > 4)) {
801                 printf("Usage: %s [access_mask] [acb_mask] [size]\n", argv[0]);
802                 return NT_STATUS_OK;
803         }
804
805         if (argc > 1) {
806                 sscanf(argv[1], "%x", &access_mask);
807         }
808
809         if (argc > 2) {
810                 sscanf(argv[2], "%x", &acb_mask);
811         }
812
813         if (argc > 3) {
814                 sscanf(argv[3], "%x", &size);
815         }
816
817         /* Get sam policy handle */
818
819         result = rpccli_try_samr_connects(cli, mem_ctx,
820                                           MAXIMUM_ALLOWED_ACCESS,
821                                           &connect_pol);
822
823         if (!NT_STATUS_IS_OK(result))
824                 goto done;
825
826         /* Get domain policy handle */
827
828         result = get_domain_handle(cli, mem_ctx, "domain",
829                                    &connect_pol,
830                                    access_mask,
831                                    &domain_sid,
832                                    &domain_pol);
833         if (!NT_STATUS_IS_OK(result))
834                 goto done;
835
836         /* Enumerate domain users */
837
838         start_idx = 0;
839
840         do {
841                 result = rpccli_samr_EnumDomainUsers(cli, mem_ctx,
842                                                      &domain_pol,
843                                                      &start_idx,
844                                                      acb_mask,
845                                                      &dom_users,
846                                                      size,
847                                                      &num_dom_users);
848
849                 if (NT_STATUS_IS_OK(result) ||
850                     NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES)) {
851
852                         for (i = 0; i < num_dom_users; i++)
853                                printf("user:[%s] rid:[0x%x]\n",
854                                        dom_users->entries[i].name.string,
855                                        dom_users->entries[i].idx);
856                 }
857
858         } while (NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES));
859
860  done:
861         if (is_valid_policy_hnd(&domain_pol))
862                 rpccli_samr_Close(cli, mem_ctx, &domain_pol);
863
864         if (is_valid_policy_hnd(&connect_pol))
865                 rpccli_samr_Close(cli, mem_ctx, &connect_pol);
866
867         return result;
868 }
869
870 /* Enumerate domain groups */
871
872 static NTSTATUS cmd_samr_enum_dom_groups(struct rpc_pipe_client *cli,
873                                          TALLOC_CTX *mem_ctx,
874                                          int argc, const char **argv)
875 {
876         struct policy_handle connect_pol, domain_pol;
877         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
878         uint32 start_idx, num_dom_groups, i;
879         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
880         struct samr_SamArray *dom_groups = NULL;
881         uint32_t size = 0xffff;
882
883         if ((argc < 1) || (argc > 3)) {
884                 printf("Usage: %s [access_mask] [max_size]\n", argv[0]);
885                 return NT_STATUS_OK;
886         }
887
888         if (argc > 1) {
889                 sscanf(argv[1], "%x", &access_mask);
890         }
891
892         if (argc > 2) {
893                 sscanf(argv[2], "%x", &size);
894         }
895
896         /* Get sam policy handle */
897
898         result = rpccli_try_samr_connects(cli, mem_ctx,
899                                           MAXIMUM_ALLOWED_ACCESS,
900                                           &connect_pol);
901
902         if (!NT_STATUS_IS_OK(result))
903                 goto done;
904
905         /* Get domain policy handle */
906
907         result = get_domain_handle(cli, mem_ctx, "domain",
908                                    &connect_pol,
909                                    access_mask,
910                                    &domain_sid,
911                                    &domain_pol);
912         if (!NT_STATUS_IS_OK(result))
913                 goto done;
914
915         /* Enumerate domain groups */
916
917         start_idx = 0;
918
919         do {
920                 result = rpccli_samr_EnumDomainGroups(cli, mem_ctx,
921                                                       &domain_pol,
922                                                       &start_idx,
923                                                       &dom_groups,
924                                                       size,
925                                                       &num_dom_groups);
926                 if (NT_STATUS_IS_OK(result) ||
927                     NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES)) {
928
929                         for (i = 0; i < num_dom_groups; i++)
930                                 printf("group:[%s] rid:[0x%x]\n",
931                                        dom_groups->entries[i].name.string,
932                                        dom_groups->entries[i].idx);
933                 }
934
935         } while (NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES));
936
937  done:
938         if (is_valid_policy_hnd(&domain_pol))
939                 rpccli_samr_Close(cli, mem_ctx, &domain_pol);
940
941         if (is_valid_policy_hnd(&connect_pol))
942                 rpccli_samr_Close(cli, mem_ctx, &connect_pol);
943
944         return result;
945 }
946
947 /* Enumerate alias groups */
948
949 static NTSTATUS cmd_samr_enum_als_groups(struct rpc_pipe_client *cli,
950                                          TALLOC_CTX *mem_ctx,
951                                          int argc, const char **argv)
952 {
953         struct policy_handle connect_pol, domain_pol;
954         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
955         uint32 start_idx, num_als_groups, i;
956         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
957         struct samr_SamArray *als_groups = NULL;
958         uint32_t size = 0xffff;
959
960         if ((argc < 2) || (argc > 4)) {
961                 printf("Usage: %s builtin|domain [access mask] [max_size]\n", argv[0]);
962                 return NT_STATUS_OK;
963         }
964
965         if (argc > 2) {
966                 sscanf(argv[2], "%x", &access_mask);
967         }
968
969         if (argc > 3) {
970                 sscanf(argv[3], "%x", &size);
971         }
972
973         /* Get sam policy handle */
974
975         result = rpccli_try_samr_connects(cli, mem_ctx,
976                                           MAXIMUM_ALLOWED_ACCESS,
977                                           &connect_pol);
978
979         if (!NT_STATUS_IS_OK(result))
980                 goto done;
981
982         /* Get domain policy handle */
983
984         result = get_domain_handle(cli, mem_ctx, argv[1],
985                                    &connect_pol,
986                                    access_mask,
987                                    &domain_sid,
988                                    &domain_pol);
989
990         if (!NT_STATUS_IS_OK(result))
991                 goto done;
992
993         /* Enumerate alias groups */
994
995         start_idx = 0;
996
997         do {
998                 result = rpccli_samr_EnumDomainAliases(cli, mem_ctx,
999                                                        &domain_pol,
1000                                                        &start_idx,
1001                                                        &als_groups,
1002                                                        size,
1003                                                        &num_als_groups);
1004
1005                 if (NT_STATUS_IS_OK(result) ||
1006                     NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES)) {
1007
1008                         for (i = 0; i < num_als_groups; i++)
1009                                 printf("group:[%s] rid:[0x%x]\n",
1010                                        als_groups->entries[i].name.string,
1011                                        als_groups->entries[i].idx);
1012                 }
1013         } while (NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES));
1014
1015  done:
1016         if (is_valid_policy_hnd(&domain_pol))
1017                 rpccli_samr_Close(cli, mem_ctx, &domain_pol);
1018
1019         if (is_valid_policy_hnd(&connect_pol))
1020                 rpccli_samr_Close(cli, mem_ctx, &connect_pol);
1021
1022         return result;
1023 }
1024
1025 /* Enumerate domains */
1026
1027 static NTSTATUS cmd_samr_enum_domains(struct rpc_pipe_client *cli,
1028                                       TALLOC_CTX *mem_ctx,
1029                                       int argc, const char **argv)
1030 {
1031         struct policy_handle connect_pol;
1032         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1033         uint32 start_idx, size, num_entries, i;
1034         uint32 access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1035         struct samr_SamArray *sam = NULL;
1036
1037         if ((argc < 1) || (argc > 2)) {
1038                 printf("Usage: %s [access mask]\n", argv[0]);
1039                 return NT_STATUS_OK;
1040         }
1041
1042         if (argc > 1) {
1043                 sscanf(argv[1], "%x", &access_mask);
1044         }
1045
1046         /* Get sam policy handle */
1047
1048         result = rpccli_try_samr_connects(cli, mem_ctx,
1049                                           access_mask,
1050                                           &connect_pol);
1051
1052         if (!NT_STATUS_IS_OK(result)) {
1053                 goto done;
1054         }
1055
1056         /* Enumerate alias groups */
1057
1058         start_idx = 0;
1059         size = 0xffff;
1060
1061         do {
1062                 result = rpccli_samr_EnumDomains(cli, mem_ctx,
1063                                                  &connect_pol,
1064                                                  &start_idx,
1065                                                  &sam,
1066                                                  size,
1067                                                  &num_entries);
1068
1069                 if (NT_STATUS_IS_OK(result) ||
1070                     NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES)) {
1071
1072                         for (i = 0; i < num_entries; i++)
1073                                 printf("name:[%s] idx:[0x%x]\n",
1074                                        sam->entries[i].name.string,
1075                                        sam->entries[i].idx);
1076                 }
1077         } while (NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES));
1078
1079  done:
1080         if (is_valid_policy_hnd(&connect_pol)) {
1081                 rpccli_samr_Close(cli, mem_ctx, &connect_pol);
1082         }
1083
1084         return result;
1085 }
1086
1087
1088 /* Query alias membership */
1089
1090 static NTSTATUS cmd_samr_query_aliasmem(struct rpc_pipe_client *cli,
1091                                         TALLOC_CTX *mem_ctx,
1092                                         int argc, const char **argv)
1093 {
1094         struct policy_handle connect_pol, domain_pol, alias_pol;
1095         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1096         uint32 alias_rid, i;
1097         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1098         struct lsa_SidArray sid_array;
1099
1100         if ((argc < 3) || (argc > 4)) {
1101                 printf("Usage: %s builtin|domain rid [access mask]\n", argv[0]);
1102                 return NT_STATUS_OK;
1103         }
1104
1105         sscanf(argv[2], "%i", &alias_rid);
1106
1107         if (argc > 3)
1108                 sscanf(argv[3], "%x", &access_mask);
1109
1110         /* Open SAMR handle */
1111
1112         result = rpccli_try_samr_connects(cli, mem_ctx,
1113                                           MAXIMUM_ALLOWED_ACCESS,
1114                                           &connect_pol);
1115
1116         if (!NT_STATUS_IS_OK(result))
1117                 goto done;
1118
1119         /* Open handle on domain */
1120
1121         result = get_domain_handle(cli, mem_ctx, argv[1],
1122                                    &connect_pol,
1123                                    MAXIMUM_ALLOWED_ACCESS,
1124                                    &domain_sid,
1125                                    &domain_pol);
1126
1127         if (!NT_STATUS_IS_OK(result))
1128                 goto done;
1129
1130         /* Open handle on alias */
1131
1132         result = rpccli_samr_OpenAlias(cli, mem_ctx,
1133                                        &domain_pol,
1134                                        access_mask,
1135                                        alias_rid,
1136                                        &alias_pol);
1137         if (!NT_STATUS_IS_OK(result))
1138                 goto done;
1139
1140         result = rpccli_samr_GetMembersInAlias(cli, mem_ctx,
1141                                                &alias_pol,
1142                                                &sid_array);
1143
1144         if (!NT_STATUS_IS_OK(result))
1145                 goto done;
1146
1147         for (i = 0; i < sid_array.num_sids; i++) {
1148                 fstring sid_str;
1149
1150                 sid_to_fstring(sid_str, sid_array.sids[i].sid);
1151                 printf("\tsid:[%s]\n", sid_str);
1152         }
1153
1154         rpccli_samr_Close(cli, mem_ctx, &alias_pol);
1155         rpccli_samr_Close(cli, mem_ctx, &domain_pol);
1156         rpccli_samr_Close(cli, mem_ctx, &connect_pol);
1157  done:
1158         return result;
1159 }
1160
1161 /* Query alias info */
1162
1163 static NTSTATUS cmd_samr_query_aliasinfo(struct rpc_pipe_client *cli,
1164                                          TALLOC_CTX *mem_ctx,
1165                                          int argc, const char **argv)
1166 {
1167         struct policy_handle connect_pol, domain_pol, alias_pol;
1168         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1169         uint32_t alias_rid;
1170         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1171         union samr_AliasInfo *info = NULL;
1172         enum samr_AliasInfoEnum level = ALIASINFOALL;
1173
1174         if ((argc < 3) || (argc > 4)) {
1175                 printf("Usage: %s builtin|domain rid [level] [access mask]\n",
1176                         argv[0]);
1177                 return NT_STATUS_OK;
1178         }
1179
1180         sscanf(argv[2], "%i", &alias_rid);
1181
1182         if (argc > 2) {
1183                 level = atoi(argv[3]);
1184         }
1185
1186         if (argc > 3) {
1187                 sscanf(argv[4], "%x", &access_mask);
1188         }
1189
1190         /* Open SAMR handle */
1191
1192         result = rpccli_try_samr_connects(cli, mem_ctx,
1193                                           SEC_FLAG_MAXIMUM_ALLOWED,
1194                                           &connect_pol);
1195
1196         if (!NT_STATUS_IS_OK(result)) {
1197                 goto done;
1198         }
1199
1200         /* Open handle on domain */
1201
1202         result = get_domain_handle(cli, mem_ctx, argv[1],
1203                                    &connect_pol,
1204                                    SEC_FLAG_MAXIMUM_ALLOWED,
1205                                    &domain_sid,
1206                                    &domain_pol);
1207
1208         if (!NT_STATUS_IS_OK(result)) {
1209                 goto done;
1210         }
1211
1212         /* Open handle on alias */
1213
1214         result = rpccli_samr_OpenAlias(cli, mem_ctx,
1215                                        &domain_pol,
1216                                        access_mask,
1217                                        alias_rid,
1218                                        &alias_pol);
1219         if (!NT_STATUS_IS_OK(result)) {
1220                 goto done;
1221         }
1222
1223         result = rpccli_samr_QueryAliasInfo(cli, mem_ctx,
1224                                             &alias_pol,
1225                                             level,
1226                                             &info);
1227
1228         if (!NT_STATUS_IS_OK(result)) {
1229                 goto done;
1230         }
1231
1232         switch (level) {
1233                 case ALIASINFOALL:
1234                         printf("Name: %s\n", info->all.name.string);
1235                         printf("Description: %s\n", info->all.description.string);
1236                         printf("Num Members: %d\n", info->all.num_members);
1237                         break;
1238                 case ALIASINFONAME:
1239                         printf("Name: %s\n", info->name.string);
1240                         break;
1241                 case ALIASINFODESCRIPTION:
1242                         printf("Description: %s\n", info->description.string);
1243                         break;
1244                 default:
1245                         break;
1246         }
1247
1248         rpccli_samr_Close(cli, mem_ctx, &alias_pol);
1249         rpccli_samr_Close(cli, mem_ctx, &domain_pol);
1250         rpccli_samr_Close(cli, mem_ctx, &connect_pol);
1251  done:
1252         return result;
1253 }
1254
1255
1256 /* Query delete an alias membership */
1257
1258 static NTSTATUS cmd_samr_delete_alias(struct rpc_pipe_client *cli,
1259                                       TALLOC_CTX *mem_ctx,
1260                                       int argc, const char **argv)
1261 {
1262         struct policy_handle connect_pol, domain_pol, alias_pol;
1263         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1264         uint32 alias_rid;
1265         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1266
1267         if (argc != 3) {
1268                 printf("Usage: %s builtin|domain [rid|name]\n", argv[0]);
1269                 return NT_STATUS_OK;
1270         }
1271
1272         alias_rid = strtoul(argv[2], NULL, 10);
1273
1274         /* Open SAMR handle */
1275
1276         result = rpccli_try_samr_connects(cli, mem_ctx,
1277                                           MAXIMUM_ALLOWED_ACCESS,
1278                                           &connect_pol);
1279
1280         if (!NT_STATUS_IS_OK(result))
1281                 goto done;
1282
1283         /* Open handle on domain */
1284
1285         result = get_domain_handle(cli, mem_ctx, argv[1],
1286                                    &connect_pol,
1287                                    MAXIMUM_ALLOWED_ACCESS,
1288                                    &domain_sid,
1289                                    &domain_pol);
1290
1291         if (!NT_STATUS_IS_OK(result))
1292                 goto done;
1293
1294         /* Open handle on alias */
1295
1296         result = rpccli_samr_OpenAlias(cli, mem_ctx,
1297                                        &domain_pol,
1298                                        access_mask,
1299                                        alias_rid,
1300                                        &alias_pol);
1301         if (!NT_STATUS_IS_OK(result) && (alias_rid == 0)) {
1302                 /* Probably this was a user name, try lookupnames */
1303                 struct samr_Ids rids, types;
1304                 struct lsa_String lsa_acct_name;
1305
1306                 init_lsa_String(&lsa_acct_name, argv[2]);
1307
1308                 result = rpccli_samr_LookupNames(cli, mem_ctx,
1309                                                  &domain_pol,
1310                                                  1,
1311                                                  &lsa_acct_name,
1312                                                  &rids,
1313                                                  &types);
1314
1315                 if (NT_STATUS_IS_OK(result)) {
1316                         result = rpccli_samr_OpenAlias(cli, mem_ctx,
1317                                                        &domain_pol,
1318                                                        access_mask,
1319                                                        rids.ids[0],
1320                                                        &alias_pol);
1321                 }
1322         }
1323
1324         result = rpccli_samr_DeleteDomAlias(cli, mem_ctx,
1325                                             &alias_pol);
1326
1327         if (!NT_STATUS_IS_OK(result))
1328                 goto done;
1329
1330         rpccli_samr_Close(cli, mem_ctx, &domain_pol);
1331         rpccli_samr_Close(cli, mem_ctx, &connect_pol);
1332  done:
1333         return result;
1334 }
1335
1336 /* Query display info */
1337
1338 static NTSTATUS cmd_samr_query_dispinfo_internal(struct rpc_pipe_client *cli,
1339                                                  TALLOC_CTX *mem_ctx,
1340                                                  int argc, const char **argv,
1341                                                  uint32_t opcode)
1342 {
1343         struct policy_handle connect_pol, domain_pol;
1344         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1345         uint32 start_idx=0, max_entries=250, max_size = 0xffff, num_entries = 0, i;
1346         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1347         uint32 info_level = 1;
1348         union samr_DispInfo info;
1349         int loop_count = 0;
1350         bool got_params = False; /* Use get_query_dispinfo_params() or not? */
1351         uint32_t total_size, returned_size;
1352
1353         if (argc > 6) {
1354                 printf("Usage: %s [info level] [start index] [max entries] [max size] [access mask]\n", argv[0]);
1355                 return NT_STATUS_OK;
1356         }
1357
1358         if (argc >= 2)
1359                 sscanf(argv[1], "%i", &info_level);
1360
1361         if (argc >= 3)
1362                 sscanf(argv[2], "%i", &start_idx);
1363
1364         if (argc >= 4) {
1365                 sscanf(argv[3], "%i", &max_entries);
1366                 got_params = True;
1367         }
1368
1369         if (argc >= 5) {
1370                 sscanf(argv[4], "%i", &max_size);
1371                 got_params = True;
1372         }
1373
1374         if (argc >= 6)
1375                 sscanf(argv[5], "%x", &access_mask);
1376
1377         /* Get sam policy handle */
1378
1379         result = rpccli_try_samr_connects(cli, mem_ctx,
1380                                           MAXIMUM_ALLOWED_ACCESS,
1381                                           &connect_pol);
1382
1383         if (!NT_STATUS_IS_OK(result))
1384                 goto done;
1385
1386         /* Get domain policy handle */
1387
1388         result = rpccli_samr_OpenDomain(cli, mem_ctx,
1389                                         &connect_pol,
1390                                         access_mask,
1391                                         &domain_sid,
1392                                         &domain_pol);
1393
1394         if (!NT_STATUS_IS_OK(result))
1395                 goto done;
1396
1397         /* Query display info */
1398
1399         do {
1400
1401                 if (!got_params)
1402                         get_query_dispinfo_params(
1403                                 loop_count, &max_entries, &max_size);
1404
1405                 switch (opcode) {
1406                 case NDR_SAMR_QUERYDISPLAYINFO:
1407                         result = rpccli_samr_QueryDisplayInfo(cli, mem_ctx,
1408                                                               &domain_pol,
1409                                                               info_level,
1410                                                               start_idx,
1411                                                               max_entries,
1412                                                               max_size,
1413                                                               &total_size,
1414                                                               &returned_size,
1415                                                               &info);
1416                         break;
1417                 case NDR_SAMR_QUERYDISPLAYINFO2:
1418                         result = rpccli_samr_QueryDisplayInfo2(cli, mem_ctx,
1419                                                                &domain_pol,
1420                                                                info_level,
1421                                                                start_idx,
1422                                                                max_entries,
1423                                                                max_size,
1424                                                                &total_size,
1425                                                                &returned_size,
1426                                                                &info);
1427
1428                         break;
1429                 case NDR_SAMR_QUERYDISPLAYINFO3:
1430                         result = rpccli_samr_QueryDisplayInfo3(cli, mem_ctx,
1431                                                                &domain_pol,
1432                                                                info_level,
1433                                                                start_idx,
1434                                                                max_entries,
1435                                                                max_size,
1436                                                                &total_size,
1437                                                                &returned_size,
1438                                                                &info);
1439
1440                         break;
1441                 default:
1442                         return NT_STATUS_INVALID_PARAMETER;
1443                 }
1444
1445                 if (!NT_STATUS_IS_OK(result) &&
1446                     !NT_STATUS_EQUAL(result, NT_STATUS_NO_MORE_ENTRIES) &&
1447                     !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
1448                         break;
1449                 }
1450
1451                 loop_count++;
1452
1453                 switch (info_level) {
1454                         case 1:
1455                                 num_entries = info.info1.count;
1456                                 break;
1457                         case 2:
1458                                 num_entries = info.info2.count;
1459                                 break;
1460                         case 3:
1461                                 num_entries = info.info3.count;
1462                                 break;
1463                         case 4:
1464                                 num_entries = info.info4.count;
1465                                 break;
1466                         case 5:
1467                                 num_entries = info.info5.count;
1468                                 break;
1469                         default:
1470                                 break;
1471                 }
1472
1473                 start_idx += num_entries;
1474
1475                 if (num_entries == 0)
1476                         break;
1477
1478                 for (i = 0; i < num_entries; i++) {
1479                         switch (info_level) {
1480                         case 1:
1481                                 display_sam_info_1(&info.info1.entries[i]);
1482                                 break;
1483                         case 2:
1484                                 display_sam_info_2(&info.info2.entries[i]);
1485                                 break;
1486                         case 3:
1487                                 display_sam_info_3(&info.info3.entries[i]);
1488                                 break;
1489                         case 4:
1490                                 display_sam_info_4(&info.info4.entries[i]);
1491                                 break;
1492                         case 5:
1493                                 display_sam_info_5(&info.info5.entries[i]);
1494                                 break;
1495                         }
1496                 }
1497         } while ( NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
1498
1499         rpccli_samr_Close(cli, mem_ctx, &domain_pol);
1500         rpccli_samr_Close(cli, mem_ctx, &connect_pol);
1501  done:
1502         return result;
1503 }
1504
1505 static NTSTATUS cmd_samr_query_dispinfo(struct rpc_pipe_client *cli,
1506                                         TALLOC_CTX *mem_ctx,
1507                                         int argc, const char **argv)
1508 {
1509         return cmd_samr_query_dispinfo_internal(cli, mem_ctx, argc, argv,
1510                                                 NDR_SAMR_QUERYDISPLAYINFO);
1511 }
1512
1513 static NTSTATUS cmd_samr_query_dispinfo2(struct rpc_pipe_client *cli,
1514                                          TALLOC_CTX *mem_ctx,
1515                                          int argc, const char **argv)
1516 {
1517         return cmd_samr_query_dispinfo_internal(cli, mem_ctx, argc, argv,
1518                                                 NDR_SAMR_QUERYDISPLAYINFO2);
1519 }
1520
1521 static NTSTATUS cmd_samr_query_dispinfo3(struct rpc_pipe_client *cli,
1522                                          TALLOC_CTX *mem_ctx,
1523                                          int argc, const char **argv)
1524 {
1525         return cmd_samr_query_dispinfo_internal(cli, mem_ctx, argc, argv,
1526                                                 NDR_SAMR_QUERYDISPLAYINFO3);
1527 }
1528
1529 /* Query domain info */
1530
1531 static NTSTATUS cmd_samr_query_dominfo(struct rpc_pipe_client *cli,
1532                                        TALLOC_CTX *mem_ctx,
1533                                        int argc, const char **argv)
1534 {
1535         struct policy_handle connect_pol, domain_pol;
1536         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1537         uint32 switch_level = 2;
1538         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1539         union samr_DomainInfo *info = NULL;
1540
1541         if (argc > 3) {
1542                 printf("Usage: %s [info level] [access mask]\n", argv[0]);
1543                 return NT_STATUS_OK;
1544         }
1545
1546         if (argc > 1)
1547                 sscanf(argv[1], "%i", &switch_level);
1548
1549         if (argc > 2)
1550                 sscanf(argv[2], "%x", &access_mask);
1551
1552         /* Get sam policy handle */
1553
1554         result = rpccli_try_samr_connects(cli, mem_ctx,
1555                                           MAXIMUM_ALLOWED_ACCESS,
1556                                           &connect_pol);
1557
1558         if (!NT_STATUS_IS_OK(result))
1559                 goto done;
1560
1561         /* Get domain policy handle */
1562
1563         result = rpccli_samr_OpenDomain(cli, mem_ctx,
1564                                         &connect_pol,
1565                                         access_mask,
1566                                         &domain_sid,
1567                                         &domain_pol);
1568
1569         if (!NT_STATUS_IS_OK(result))
1570                 goto done;
1571
1572         /* Query domain info */
1573
1574         result = rpccli_samr_QueryDomainInfo(cli, mem_ctx,
1575                                              &domain_pol,
1576                                              switch_level,
1577                                              &info);
1578
1579         if (!NT_STATUS_IS_OK(result))
1580                 goto done;
1581
1582         /* Display domain info */
1583
1584         switch (switch_level) {
1585         case 1:
1586                 display_sam_dom_info_1(&info->info1);
1587                 break;
1588         case 2:
1589                 display_sam_dom_info_2(&info->general);
1590                 break;
1591         case 3:
1592                 display_sam_dom_info_3(&info->info3);
1593                 break;
1594         case 4:
1595                 display_sam_dom_info_4(&info->oem);
1596                 break;
1597         case 5:
1598                 display_sam_dom_info_5(&info->info5);
1599                 break;
1600         case 6:
1601                 display_sam_dom_info_6(&info->info6);
1602                 break;
1603         case 7:
1604                 display_sam_dom_info_7(&info->info7);
1605                 break;
1606         case 8:
1607                 display_sam_dom_info_8(&info->info8);
1608                 break;
1609         case 9:
1610                 display_sam_dom_info_9(&info->info9);
1611                 break;
1612         case 12:
1613                 display_sam_dom_info_12(&info->info12);
1614                 break;
1615         case 13:
1616                 display_sam_dom_info_13(&info->info13);
1617                 break;
1618
1619         default:
1620                 printf("cannot display domain info for switch value %d\n",
1621                        switch_level);
1622                 break;
1623         }
1624
1625  done:
1626
1627         rpccli_samr_Close(cli, mem_ctx, &domain_pol);
1628         rpccli_samr_Close(cli, mem_ctx, &connect_pol);
1629         return result;
1630 }
1631
1632 /* Create domain user */
1633
1634 static NTSTATUS cmd_samr_create_dom_user(struct rpc_pipe_client *cli,
1635                                          TALLOC_CTX *mem_ctx,
1636                                          int argc, const char **argv)
1637 {
1638         struct policy_handle connect_pol, domain_pol, user_pol;
1639         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1640         struct lsa_String acct_name;
1641         uint32 acb_info;
1642         uint32 acct_flags, user_rid;
1643         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1644         uint32_t access_granted = 0;
1645
1646         if ((argc < 2) || (argc > 3)) {
1647                 printf("Usage: %s username [access mask]\n", argv[0]);
1648                 return NT_STATUS_OK;
1649         }
1650
1651         init_lsa_String(&acct_name, argv[1]);
1652
1653         if (argc > 2)
1654                 sscanf(argv[2], "%x", &access_mask);
1655
1656         /* Get sam policy handle */
1657
1658         result = rpccli_try_samr_connects(cli, mem_ctx,
1659                                           MAXIMUM_ALLOWED_ACCESS,
1660                                           &connect_pol);
1661
1662         if (!NT_STATUS_IS_OK(result))
1663                 goto done;
1664
1665         /* Get domain policy handle */
1666
1667         result = rpccli_samr_OpenDomain(cli, mem_ctx,
1668                                         &connect_pol,
1669                                         access_mask,
1670                                         &domain_sid,
1671                                         &domain_pol);
1672
1673         if (!NT_STATUS_IS_OK(result))
1674                 goto done;
1675
1676         /* Create domain user */
1677
1678         acb_info = ACB_NORMAL;
1679         acct_flags = SEC_GENERIC_READ | SEC_GENERIC_WRITE | SEC_GENERIC_EXECUTE |
1680                      SEC_STD_WRITE_DAC | SEC_STD_DELETE |
1681                      SAMR_USER_ACCESS_SET_PASSWORD |
1682                      SAMR_USER_ACCESS_GET_ATTRIBUTES |
1683                      SAMR_USER_ACCESS_SET_ATTRIBUTES;
1684
1685         result = rpccli_samr_CreateUser2(cli, mem_ctx,
1686                                          &domain_pol,
1687                                          &acct_name,
1688                                          acb_info,
1689                                          acct_flags,
1690                                          &user_pol,
1691                                          &access_granted,
1692                                          &user_rid);
1693
1694         if (!NT_STATUS_IS_OK(result))
1695                 goto done;
1696
1697         result = rpccli_samr_Close(cli, mem_ctx, &user_pol);
1698         if (!NT_STATUS_IS_OK(result)) goto done;
1699
1700         result = rpccli_samr_Close(cli, mem_ctx, &domain_pol);
1701         if (!NT_STATUS_IS_OK(result)) goto done;
1702
1703         result = rpccli_samr_Close(cli, mem_ctx, &connect_pol);
1704         if (!NT_STATUS_IS_OK(result)) goto done;
1705
1706  done:
1707         return result;
1708 }
1709
1710 /* Create domain group */
1711
1712 static NTSTATUS cmd_samr_create_dom_group(struct rpc_pipe_client *cli,
1713                                           TALLOC_CTX *mem_ctx,
1714                                           int argc, const char **argv)
1715 {
1716         struct policy_handle connect_pol, domain_pol, group_pol;
1717         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1718         struct lsa_String grp_name;
1719         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1720         uint32_t rid = 0;
1721
1722         if ((argc < 2) || (argc > 3)) {
1723                 printf("Usage: %s groupname [access mask]\n", argv[0]);
1724                 return NT_STATUS_OK;
1725         }
1726
1727         init_lsa_String(&grp_name, argv[1]);
1728
1729         if (argc > 2)
1730                 sscanf(argv[2], "%x", &access_mask);
1731
1732         /* Get sam policy handle */
1733
1734         result = rpccli_try_samr_connects(cli, mem_ctx,
1735                                           MAXIMUM_ALLOWED_ACCESS,
1736                                           &connect_pol);
1737
1738         if (!NT_STATUS_IS_OK(result))
1739                 goto done;
1740
1741         /* Get domain policy handle */
1742
1743         result = rpccli_samr_OpenDomain(cli, mem_ctx,
1744                                         &connect_pol,
1745                                         access_mask,
1746                                         &domain_sid,
1747                                         &domain_pol);
1748
1749         if (!NT_STATUS_IS_OK(result))
1750                 goto done;
1751
1752         /* Create domain user */
1753         result = rpccli_samr_CreateDomainGroup(cli, mem_ctx,
1754                                                &domain_pol,
1755                                                &grp_name,
1756                                                MAXIMUM_ALLOWED_ACCESS,
1757                                                &group_pol,
1758                                                &rid);
1759
1760         if (!NT_STATUS_IS_OK(result))
1761                 goto done;
1762
1763         result = rpccli_samr_Close(cli, mem_ctx, &group_pol);
1764         if (!NT_STATUS_IS_OK(result)) goto done;
1765
1766         result = rpccli_samr_Close(cli, mem_ctx, &domain_pol);
1767         if (!NT_STATUS_IS_OK(result)) goto done;
1768
1769         result = rpccli_samr_Close(cli, mem_ctx, &connect_pol);
1770         if (!NT_STATUS_IS_OK(result)) goto done;
1771
1772  done:
1773         return result;
1774 }
1775
1776 /* Create domain alias */
1777
1778 static NTSTATUS cmd_samr_create_dom_alias(struct rpc_pipe_client *cli,
1779                                           TALLOC_CTX *mem_ctx,
1780                                           int argc, const char **argv)
1781 {
1782         struct policy_handle connect_pol, domain_pol, alias_pol;
1783         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1784         struct lsa_String alias_name;
1785         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1786         uint32_t rid = 0;
1787
1788         if ((argc < 2) || (argc > 3)) {
1789                 printf("Usage: %s aliasname [access mask]\n", argv[0]);
1790                 return NT_STATUS_OK;
1791         }
1792
1793         init_lsa_String(&alias_name, argv[1]);
1794
1795         if (argc > 2)
1796                 sscanf(argv[2], "%x", &access_mask);
1797
1798         /* Get sam policy handle */
1799
1800         result = rpccli_try_samr_connects(cli, mem_ctx,
1801                                           MAXIMUM_ALLOWED_ACCESS,
1802                                           &connect_pol);
1803
1804         if (!NT_STATUS_IS_OK(result))
1805                 goto done;
1806
1807         /* Get domain policy handle */
1808
1809         result = rpccli_samr_OpenDomain(cli, mem_ctx,
1810                                         &connect_pol,
1811                                         access_mask,
1812                                         &domain_sid,
1813                                         &domain_pol);
1814
1815         if (!NT_STATUS_IS_OK(result))
1816                 goto done;
1817
1818         /* Create domain user */
1819
1820         result = rpccli_samr_CreateDomAlias(cli, mem_ctx,
1821                                             &domain_pol,
1822                                             &alias_name,
1823                                             MAXIMUM_ALLOWED_ACCESS,
1824                                             &alias_pol,
1825                                             &rid);
1826
1827         if (!NT_STATUS_IS_OK(result))
1828                 goto done;
1829
1830         result = rpccli_samr_Close(cli, mem_ctx, &alias_pol);
1831         if (!NT_STATUS_IS_OK(result)) goto done;
1832
1833         result = rpccli_samr_Close(cli, mem_ctx, &domain_pol);
1834         if (!NT_STATUS_IS_OK(result)) goto done;
1835
1836         result = rpccli_samr_Close(cli, mem_ctx, &connect_pol);
1837         if (!NT_STATUS_IS_OK(result)) goto done;
1838
1839  done:
1840         return result;
1841 }
1842
1843 /* Lookup sam names */
1844
1845 static NTSTATUS cmd_samr_lookup_names(struct rpc_pipe_client *cli,
1846                                       TALLOC_CTX *mem_ctx,
1847                                       int argc, const char **argv)
1848 {
1849         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1850         struct policy_handle connect_pol, domain_pol;
1851         uint32 num_names;
1852         struct samr_Ids rids, name_types;
1853         int i;
1854         struct lsa_String *names = NULL;;
1855
1856         if (argc < 3) {
1857                 printf("Usage: %s  domain|builtin name1 [name2 [name3] [...]]\n", argv[0]);
1858                 printf("check on the domain SID: S-1-5-21-x-y-z\n");
1859                 printf("or check on the builtin SID: S-1-5-32\n");
1860                 return NT_STATUS_OK;
1861         }
1862
1863         /* Get sam policy and domain handles */
1864
1865         result = rpccli_try_samr_connects(cli, mem_ctx,
1866                                           MAXIMUM_ALLOWED_ACCESS,
1867                                           &connect_pol);
1868
1869         if (!NT_STATUS_IS_OK(result))
1870                 goto done;
1871
1872         result = get_domain_handle(cli, mem_ctx, argv[1],
1873                                    &connect_pol,
1874                                    MAXIMUM_ALLOWED_ACCESS,
1875                                    &domain_sid,
1876                                    &domain_pol);
1877
1878         if (!NT_STATUS_IS_OK(result))
1879                 goto done;
1880
1881         /* Look up names */
1882
1883         num_names = argc - 2;
1884
1885         if ((names = TALLOC_ARRAY(mem_ctx, struct lsa_String, num_names)) == NULL) {
1886                 rpccli_samr_Close(cli, mem_ctx, &domain_pol);
1887                 rpccli_samr_Close(cli, mem_ctx, &connect_pol);
1888                 result = NT_STATUS_NO_MEMORY;
1889                 goto done;
1890         }
1891
1892         for (i = 0; i < num_names; i++) {
1893                 init_lsa_String(&names[i], argv[i + 2]);
1894         }
1895
1896         result = rpccli_samr_LookupNames(cli, mem_ctx,
1897                                          &domain_pol,
1898                                          num_names,
1899                                          names,
1900                                          &rids,
1901                                          &name_types);
1902
1903         if (!NT_STATUS_IS_OK(result))
1904                 goto done;
1905
1906         /* Display results */
1907
1908         for (i = 0; i < num_names; i++)
1909                 printf("name %s: 0x%x (%d)\n", names[i].string, rids.ids[i],
1910                        name_types.ids[i]);
1911
1912         rpccli_samr_Close(cli, mem_ctx, &domain_pol);
1913         rpccli_samr_Close(cli, mem_ctx, &connect_pol);
1914  done:
1915         return result;
1916 }
1917
1918 /* Lookup sam rids */
1919
1920 static NTSTATUS cmd_samr_lookup_rids(struct rpc_pipe_client *cli,
1921                                      TALLOC_CTX *mem_ctx,
1922                                      int argc, const char **argv)
1923 {
1924         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1925         struct policy_handle connect_pol, domain_pol;
1926         uint32_t num_rids, *rids;
1927         struct lsa_Strings names;
1928         struct samr_Ids types;
1929
1930         int i;
1931
1932         if (argc < 3) {
1933                 printf("Usage: %s domain|builtin rid1 [rid2 [rid3] [...]]\n", argv[0]);
1934                 return NT_STATUS_OK;
1935         }
1936
1937         /* Get sam policy and domain handles */
1938
1939         result = rpccli_try_samr_connects(cli, mem_ctx,
1940                                           MAXIMUM_ALLOWED_ACCESS,
1941                                           &connect_pol);
1942
1943         if (!NT_STATUS_IS_OK(result))
1944                 goto done;
1945
1946         result = get_domain_handle(cli, mem_ctx, argv[1],
1947                                    &connect_pol,
1948                                    MAXIMUM_ALLOWED_ACCESS,
1949                                    &domain_sid,
1950                                    &domain_pol);
1951
1952         if (!NT_STATUS_IS_OK(result))
1953                 goto done;
1954
1955         /* Look up rids */
1956
1957         num_rids = argc - 2;
1958
1959         if ((rids = TALLOC_ARRAY(mem_ctx, uint32, num_rids)) == NULL) {
1960                 rpccli_samr_Close(cli, mem_ctx, &domain_pol);
1961                 rpccli_samr_Close(cli, mem_ctx, &connect_pol);
1962                 result = NT_STATUS_NO_MEMORY;
1963                 goto done;
1964         }
1965
1966         for (i = 0; i < argc - 2; i++)
1967                 sscanf(argv[i + 2], "%i", &rids[i]);
1968
1969         result = rpccli_samr_LookupRids(cli, mem_ctx,
1970                                         &domain_pol,
1971                                         num_rids,
1972                                         rids,
1973                                         &names,
1974                                         &types);
1975
1976         if (!NT_STATUS_IS_OK(result) &&
1977             !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED))
1978                 goto done;
1979
1980         /* Display results */
1981
1982         for (i = 0; i < num_rids; i++) {
1983                 printf("rid 0x%x: %s (%d)\n",
1984                         rids[i], names.names[i].string, types.ids[i]);
1985         }
1986
1987         rpccli_samr_Close(cli, mem_ctx, &domain_pol);
1988         rpccli_samr_Close(cli, mem_ctx, &connect_pol);
1989  done:
1990         return result;
1991 }
1992
1993 /* Delete domain group */
1994
1995 static NTSTATUS cmd_samr_delete_dom_group(struct rpc_pipe_client *cli,
1996                                          TALLOC_CTX *mem_ctx,
1997                                          int argc, const char **argv)
1998 {
1999         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2000         struct policy_handle connect_pol, domain_pol, group_pol;
2001         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
2002
2003         if ((argc < 2) || (argc > 3)) {
2004                 printf("Usage: %s groupname\n", argv[0]);
2005                 return NT_STATUS_OK;
2006         }
2007
2008         if (argc > 2)
2009                 sscanf(argv[2], "%x", &access_mask);
2010
2011         /* Get sam policy and domain handles */
2012
2013         result = rpccli_try_samr_connects(cli, mem_ctx,
2014                                           MAXIMUM_ALLOWED_ACCESS,
2015                                           &connect_pol);
2016
2017         if (!NT_STATUS_IS_OK(result))
2018                 goto done;
2019
2020         result = rpccli_samr_OpenDomain(cli, mem_ctx,
2021                                         &connect_pol,
2022                                         MAXIMUM_ALLOWED_ACCESS,
2023                                         &domain_sid,
2024                                         &domain_pol);
2025
2026         if (!NT_STATUS_IS_OK(result))
2027                 goto done;
2028
2029         /* Get handle on group */
2030
2031         {
2032                 struct samr_Ids group_rids, name_types;
2033                 struct lsa_String lsa_acct_name;
2034
2035                 init_lsa_String(&lsa_acct_name, argv[1]);
2036
2037                 result = rpccli_samr_LookupNames(cli, mem_ctx,
2038                                                  &domain_pol,
2039                                                  1,
2040                                                  &lsa_acct_name,
2041                                                  &group_rids,
2042                                                  &name_types);
2043                 if (!NT_STATUS_IS_OK(result))
2044                         goto done;
2045
2046                 result = rpccli_samr_OpenGroup(cli, mem_ctx,
2047                                                &domain_pol,
2048                                                access_mask,
2049                                                group_rids.ids[0],
2050                                                &group_pol);
2051
2052                 if (!NT_STATUS_IS_OK(result))
2053                         goto done;
2054         }
2055
2056         /* Delete group */
2057
2058         result = rpccli_samr_DeleteDomainGroup(cli, mem_ctx,
2059                                                &group_pol);
2060
2061         if (!NT_STATUS_IS_OK(result))
2062                 goto done;
2063
2064         /* Display results */
2065
2066         rpccli_samr_Close(cli, mem_ctx, &group_pol);
2067         rpccli_samr_Close(cli, mem_ctx, &domain_pol);
2068         rpccli_samr_Close(cli, mem_ctx, &connect_pol);
2069
2070  done:
2071         return result;
2072 }
2073
2074 /* Delete domain user */
2075
2076 static NTSTATUS cmd_samr_delete_dom_user(struct rpc_pipe_client *cli,
2077                                          TALLOC_CTX *mem_ctx,
2078                                          int argc, const char **argv)
2079 {
2080         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2081         struct policy_handle connect_pol, domain_pol, user_pol;
2082         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
2083
2084         if ((argc < 2) || (argc > 3)) {
2085                 printf("Usage: %s username\n", argv[0]);
2086                 return NT_STATUS_OK;
2087         }
2088
2089         if (argc > 2)
2090                 sscanf(argv[2], "%x", &access_mask);
2091
2092         /* Get sam policy and domain handles */
2093
2094         result = rpccli_try_samr_connects(cli, mem_ctx,
2095                                           MAXIMUM_ALLOWED_ACCESS,
2096                                           &connect_pol);
2097
2098         if (!NT_STATUS_IS_OK(result))
2099                 goto done;
2100
2101         result = rpccli_samr_OpenDomain(cli, mem_ctx,
2102                                         &connect_pol,
2103                                         MAXIMUM_ALLOWED_ACCESS,
2104                                         &domain_sid,
2105                                         &domain_pol);
2106
2107         if (!NT_STATUS_IS_OK(result))
2108                 goto done;
2109
2110         /* Get handle on user */
2111
2112         {
2113                 struct samr_Ids user_rids, name_types;
2114                 struct lsa_String lsa_acct_name;
2115
2116                 init_lsa_String(&lsa_acct_name, argv[1]);
2117
2118                 result = rpccli_samr_LookupNames(cli, mem_ctx,
2119                                                  &domain_pol,
2120                                                  1,
2121                                                  &lsa_acct_name,
2122                                                  &user_rids,
2123                                                  &name_types);
2124
2125                 if (!NT_STATUS_IS_OK(result))
2126                         goto done;
2127
2128                 result = rpccli_samr_OpenUser(cli, mem_ctx,
2129                                               &domain_pol,
2130                                               access_mask,
2131                                               user_rids.ids[0],
2132                                               &user_pol);
2133
2134                 if (!NT_STATUS_IS_OK(result))
2135                         goto done;
2136         }
2137
2138         /* Delete user */
2139
2140         result = rpccli_samr_DeleteUser(cli, mem_ctx,
2141                                         &user_pol);
2142
2143         if (!NT_STATUS_IS_OK(result))
2144                 goto done;
2145
2146         /* Display results */
2147
2148         rpccli_samr_Close(cli, mem_ctx, &user_pol);
2149         rpccli_samr_Close(cli, mem_ctx, &domain_pol);
2150         rpccli_samr_Close(cli, mem_ctx, &connect_pol);
2151
2152  done:
2153         return result;
2154 }
2155
2156 /**********************************************************************
2157  * Query user security object
2158  */
2159 static NTSTATUS cmd_samr_query_sec_obj(struct rpc_pipe_client *cli,
2160                                     TALLOC_CTX *mem_ctx,
2161                                     int argc, const char **argv)
2162 {
2163         struct policy_handle connect_pol, domain_pol, user_pol, *pol;
2164         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2165         uint32 sec_info = SECINFO_DACL;
2166         uint32 user_rid = 0;
2167         TALLOC_CTX *ctx = NULL;
2168         struct sec_desc_buf *sec_desc_buf=NULL;
2169         bool domain = False;
2170
2171         ctx=talloc_init("cmd_samr_query_sec_obj");
2172
2173         if ((argc < 1) || (argc > 3)) {
2174                 printf("Usage: %s [rid|-d] [sec_info]\n", argv[0]);
2175                 printf("\tSpecify rid for security on user, -d for security on domain\n");
2176                 talloc_destroy(ctx);
2177                 return NT_STATUS_OK;
2178         }
2179
2180         if (argc > 1) {
2181                 if (strcmp(argv[1], "-d") == 0)
2182                         domain = True;
2183                 else
2184                         sscanf(argv[1], "%i", &user_rid);
2185         }
2186
2187         if (argc == 3) {
2188                 sec_info = atoi(argv[2]);
2189         }
2190
2191         result = rpccli_try_samr_connects(cli, mem_ctx,
2192                                           MAXIMUM_ALLOWED_ACCESS,
2193                                           &connect_pol);
2194
2195         if (!NT_STATUS_IS_OK(result))
2196                 goto done;
2197
2198         if (domain || user_rid)
2199                 result = rpccli_samr_OpenDomain(cli, mem_ctx,
2200                                                 &connect_pol,
2201                                                 MAXIMUM_ALLOWED_ACCESS,
2202                                                 &domain_sid,
2203                                                 &domain_pol);
2204
2205         if (!NT_STATUS_IS_OK(result))
2206                 goto done;
2207
2208         if (user_rid)
2209                 result = rpccli_samr_OpenUser(cli, mem_ctx,
2210                                               &domain_pol,
2211                                               MAXIMUM_ALLOWED_ACCESS,
2212                                               user_rid,
2213                                               &user_pol);
2214
2215         if (!NT_STATUS_IS_OK(result))
2216                 goto done;
2217
2218         /* Pick which query pol to use */
2219
2220         pol = &connect_pol;
2221
2222         if (domain)
2223                 pol = &domain_pol;
2224
2225         if (user_rid)
2226                 pol = &user_pol;
2227
2228         /* Query SAM security object */
2229
2230         result = rpccli_samr_QuerySecurity(cli, mem_ctx,
2231                                            pol,
2232                                            sec_info,
2233                                            &sec_desc_buf);
2234
2235         if (!NT_STATUS_IS_OK(result))
2236                 goto done;
2237
2238         display_sec_desc(sec_desc_buf->sd);
2239
2240         rpccli_samr_Close(cli, mem_ctx, &user_pol);
2241         rpccli_samr_Close(cli, mem_ctx, &domain_pol);
2242         rpccli_samr_Close(cli, mem_ctx, &connect_pol);
2243 done:
2244         talloc_destroy(ctx);
2245         return result;
2246 }
2247
2248 static NTSTATUS cmd_samr_get_usrdom_pwinfo(struct rpc_pipe_client *cli,
2249                                            TALLOC_CTX *mem_ctx,
2250                                            int argc, const char **argv)
2251 {
2252         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2253         struct policy_handle connect_pol, domain_pol, user_pol;
2254         struct samr_PwInfo info;
2255         uint32_t rid;
2256
2257         if (argc != 2) {
2258                 printf("Usage: %s rid\n", argv[0]);
2259                 return NT_STATUS_OK;
2260         }
2261
2262         sscanf(argv[1], "%i", &rid);
2263
2264         result = rpccli_try_samr_connects(cli, mem_ctx,
2265                                           MAXIMUM_ALLOWED_ACCESS,
2266                                           &connect_pol);
2267
2268         if (!NT_STATUS_IS_OK(result)) {
2269                 goto done;
2270         }
2271
2272         result = rpccli_samr_OpenDomain(cli, mem_ctx,
2273                                         &connect_pol,
2274                                         MAXIMUM_ALLOWED_ACCESS,
2275                                         &domain_sid,
2276                                         &domain_pol);
2277
2278         if (!NT_STATUS_IS_OK(result)) {
2279                 goto done;
2280         }
2281
2282         result = rpccli_samr_OpenUser(cli, mem_ctx,
2283                                       &domain_pol,
2284                                       MAXIMUM_ALLOWED_ACCESS,
2285                                       rid,
2286                                       &user_pol);
2287
2288         if (!NT_STATUS_IS_OK(result)) {
2289                 goto done;
2290         }
2291
2292         result = rpccli_samr_GetUserPwInfo(cli, mem_ctx, &user_pol, &info);
2293         if (NT_STATUS_IS_OK(result)) {
2294                 printf("min_password_length: %d\n", info.min_password_length);
2295                 printf("%s\n",
2296                         NDR_PRINT_STRUCT_STRING(mem_ctx,
2297                                 samr_PasswordProperties, &info.password_properties));
2298         }
2299
2300  done:
2301         rpccli_samr_Close(cli, mem_ctx, &user_pol);
2302         rpccli_samr_Close(cli, mem_ctx, &domain_pol);
2303         rpccli_samr_Close(cli, mem_ctx, &connect_pol);
2304
2305         return result;
2306 }
2307
2308 static NTSTATUS cmd_samr_get_dom_pwinfo(struct rpc_pipe_client *cli,
2309                                         TALLOC_CTX *mem_ctx,
2310                                         int argc, const char **argv)
2311 {
2312         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2313         struct lsa_String domain_name;
2314         struct samr_PwInfo info;
2315
2316         if (argc < 1 || argc > 3) {
2317                 printf("Usage: %s <domain>\n", argv[0]);
2318                 return NT_STATUS_OK;
2319         }
2320
2321         init_lsa_String(&domain_name, argv[1]);
2322
2323         result = rpccli_samr_GetDomPwInfo(cli, mem_ctx, &domain_name, &info);
2324
2325         if (NT_STATUS_IS_OK(result)) {
2326                 printf("min_password_length: %d\n", info.min_password_length);
2327                 display_password_properties(info.password_properties);
2328         }
2329
2330         return result;
2331 }
2332
2333 /* Look up domain name */
2334
2335 static NTSTATUS cmd_samr_lookup_domain(struct rpc_pipe_client *cli,
2336                                        TALLOC_CTX *mem_ctx,
2337                                        int argc, const char **argv)
2338 {
2339         struct policy_handle connect_pol, domain_pol;
2340         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2341         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
2342         fstring sid_string;
2343         struct lsa_String domain_name;
2344         struct dom_sid *sid = NULL;
2345
2346         if (argc != 2) {
2347                 printf("Usage: %s domain_name\n", argv[0]);
2348                 return NT_STATUS_OK;
2349         }
2350
2351         init_lsa_String(&domain_name, argv[1]);
2352
2353         result = rpccli_try_samr_connects(cli, mem_ctx,
2354                                           access_mask,
2355                                           &connect_pol);
2356
2357         if (!NT_STATUS_IS_OK(result))
2358                 goto done;
2359
2360         result = rpccli_samr_OpenDomain(cli, mem_ctx,
2361                                         &connect_pol,
2362                                         access_mask,
2363                                         &domain_sid,
2364                                         &domain_pol);
2365
2366         if (!NT_STATUS_IS_OK(result))
2367                 goto done;
2368
2369         result = rpccli_samr_LookupDomain(cli, mem_ctx,
2370                                           &connect_pol,
2371                                           &domain_name,
2372                                           &sid);
2373
2374         if (NT_STATUS_IS_OK(result)) {
2375                 sid_to_fstring(sid_string, sid);
2376                 printf("SAMR_LOOKUP_DOMAIN: Domain Name: %s Domain SID: %s\n",
2377                        argv[1], sid_string);
2378         }
2379
2380         rpccli_samr_Close(cli, mem_ctx, &domain_pol);
2381         rpccli_samr_Close(cli, mem_ctx, &connect_pol);
2382 done:
2383         return result;
2384 }
2385
2386 /* Change user password */
2387
2388 static NTSTATUS cmd_samr_chgpasswd(struct rpc_pipe_client *cli,
2389                                    TALLOC_CTX *mem_ctx,
2390                                    int argc, const char **argv)
2391 {
2392         struct policy_handle connect_pol, domain_pol, user_pol;
2393         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2394         const char *user, *oldpass, *newpass;
2395         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
2396         struct samr_Ids rids, types;
2397         struct lsa_String lsa_acct_name;
2398
2399         if (argc < 3) {
2400                 printf("Usage: %s username oldpass newpass\n", argv[0]);
2401                 return NT_STATUS_INVALID_PARAMETER;
2402         }
2403
2404         user = argv[1];
2405         oldpass = argv[2];
2406         newpass = argv[3];
2407
2408         /* Get sam policy handle */
2409
2410         result = rpccli_try_samr_connects(cli, mem_ctx,
2411                                           MAXIMUM_ALLOWED_ACCESS,
2412                                           &connect_pol);
2413
2414         if (!NT_STATUS_IS_OK(result)) {
2415                 goto done;
2416         }
2417
2418         /* Get domain policy handle */
2419
2420         result = rpccli_samr_OpenDomain(cli, mem_ctx,
2421                                         &connect_pol,
2422                                         access_mask,
2423                                         &domain_sid,
2424                                         &domain_pol);
2425
2426         if (!NT_STATUS_IS_OK(result)) {
2427                 goto done;
2428         }
2429
2430         init_lsa_String(&lsa_acct_name, user);
2431
2432         result = rpccli_samr_LookupNames(cli, mem_ctx,
2433                                          &domain_pol,
2434                                          1,
2435                                          &lsa_acct_name,
2436                                          &rids,
2437                                          &types);
2438
2439         if (!NT_STATUS_IS_OK(result)) {
2440                 goto done;
2441         }
2442
2443         result = rpccli_samr_OpenUser(cli, mem_ctx,
2444                                       &domain_pol,
2445                                       access_mask,
2446                                       rids.ids[0],
2447                                       &user_pol);
2448
2449         if (!NT_STATUS_IS_OK(result)) {
2450                 goto done;
2451         }
2452
2453         /* Change user password */
2454         result = rpccli_samr_chgpasswd_user(cli, mem_ctx,
2455                                             &user_pol,
2456                                             newpass,
2457                                             oldpass);
2458
2459         if (!NT_STATUS_IS_OK(result)) {
2460                 goto done;
2461         }
2462
2463  done:
2464         if (is_valid_policy_hnd(&user_pol)) {
2465                 rpccli_samr_Close(cli, mem_ctx, &user_pol);
2466         }
2467         if (is_valid_policy_hnd(&domain_pol)) {
2468                 rpccli_samr_Close(cli, mem_ctx, &domain_pol);
2469         }
2470         if (is_valid_policy_hnd(&connect_pol)) {
2471                 rpccli_samr_Close(cli, mem_ctx, &connect_pol);
2472         }
2473
2474         return result;
2475 }
2476
2477
2478 /* Change user password */
2479
2480 static NTSTATUS cmd_samr_chgpasswd2(struct rpc_pipe_client *cli,
2481                                     TALLOC_CTX *mem_ctx,
2482                                     int argc, const char **argv)
2483 {
2484         struct policy_handle connect_pol, domain_pol;
2485         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2486         const char *user, *oldpass, *newpass;
2487         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
2488
2489         if (argc < 3) {
2490                 printf("Usage: %s username oldpass newpass\n", argv[0]);
2491                 return NT_STATUS_INVALID_PARAMETER;
2492         }
2493
2494         user = argv[1];
2495         oldpass = argv[2];
2496         newpass = argv[3];
2497
2498         /* Get sam policy handle */
2499
2500         result = rpccli_try_samr_connects(cli, mem_ctx,
2501                                           MAXIMUM_ALLOWED_ACCESS,
2502                                           &connect_pol);
2503
2504         if (!NT_STATUS_IS_OK(result))
2505                 goto done;
2506
2507         /* Get domain policy handle */
2508
2509         result = rpccli_samr_OpenDomain(cli, mem_ctx,
2510                                         &connect_pol,
2511                                         access_mask,
2512                                         &domain_sid,
2513                                         &domain_pol);
2514
2515         if (!NT_STATUS_IS_OK(result))
2516                 goto done;
2517
2518         /* Change user password */
2519         result = rpccli_samr_chgpasswd_user2(cli, mem_ctx, user, newpass, oldpass);
2520
2521         if (!NT_STATUS_IS_OK(result))
2522                 goto done;
2523
2524         result = rpccli_samr_Close(cli, mem_ctx, &domain_pol);
2525         if (!NT_STATUS_IS_OK(result)) goto done;
2526
2527         result = rpccli_samr_Close(cli, mem_ctx, &connect_pol);
2528         if (!NT_STATUS_IS_OK(result)) goto done;
2529
2530  done:
2531         return result;
2532 }
2533
2534
2535 /* Change user password */
2536
2537 static NTSTATUS cmd_samr_chgpasswd3(struct rpc_pipe_client *cli,
2538                                     TALLOC_CTX *mem_ctx,
2539                                     int argc, const char **argv)
2540 {
2541         struct policy_handle connect_pol, domain_pol;
2542         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2543         const char *user, *oldpass, *newpass;
2544         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
2545         struct samr_DomInfo1 *info = NULL;
2546         struct userPwdChangeFailureInformation *reject = NULL;
2547
2548         if (argc < 3) {
2549                 printf("Usage: %s username oldpass newpass\n", argv[0]);
2550                 return NT_STATUS_INVALID_PARAMETER;
2551         }
2552
2553         user = argv[1];
2554         oldpass = argv[2];
2555         newpass = argv[3];
2556
2557         /* Get sam policy handle */
2558
2559         result = rpccli_try_samr_connects(cli, mem_ctx,
2560                                           MAXIMUM_ALLOWED_ACCESS,
2561                                           &connect_pol);
2562
2563         if (!NT_STATUS_IS_OK(result))
2564                 goto done;
2565
2566         /* Get domain policy handle */
2567
2568         result = rpccli_samr_OpenDomain(cli, mem_ctx,
2569                                         &connect_pol,
2570                                         access_mask,
2571                                         &domain_sid,
2572                                         &domain_pol);
2573
2574         if (!NT_STATUS_IS_OK(result))
2575                 goto done;
2576
2577         /* Change user password */
2578         result = rpccli_samr_chgpasswd_user3(cli, mem_ctx,
2579                                              user,
2580                                              newpass,
2581                                              oldpass,
2582                                              &info,
2583                                              &reject);
2584
2585         if (NT_STATUS_EQUAL(result, NT_STATUS_PASSWORD_RESTRICTION)) {
2586
2587                 display_sam_dom_info_1(info);
2588
2589                 switch (reject->extendedFailureReason) {
2590                         case SAM_PWD_CHANGE_PASSWORD_TOO_SHORT:
2591                                 d_printf("SAM_PWD_CHANGE_PASSWORD_TOO_SHORT\n");
2592                                 break;
2593                         case SAM_PWD_CHANGE_PWD_IN_HISTORY:
2594                                 d_printf("SAM_PWD_CHANGE_PWD_IN_HISTORY\n");
2595                                 break;
2596                         case SAM_PWD_CHANGE_NOT_COMPLEX:
2597                                 d_printf("SAM_PWD_CHANGE_NOT_COMPLEX\n");
2598                                 break;
2599                         default:
2600                                 d_printf("unknown reject reason: %d\n",
2601                                         reject->extendedFailureReason);
2602                                 break;
2603                 }
2604         }
2605
2606         if (!NT_STATUS_IS_OK(result))
2607                 goto done;
2608
2609         result = rpccli_samr_Close(cli, mem_ctx, &domain_pol);
2610         if (!NT_STATUS_IS_OK(result)) goto done;
2611
2612         result = rpccli_samr_Close(cli, mem_ctx, &connect_pol);
2613         if (!NT_STATUS_IS_OK(result)) goto done;
2614
2615  done:
2616         return result;
2617 }
2618
2619 static NTSTATUS cmd_samr_setuserinfo_int(struct rpc_pipe_client *cli,
2620                                          TALLOC_CTX *mem_ctx,
2621                                          int argc, const char **argv,
2622                                          int opcode)
2623 {
2624         struct policy_handle connect_pol, domain_pol, user_pol;
2625         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
2626         const char *user, *param;
2627         uint32_t access_mask = MAXIMUM_ALLOWED_ACCESS;
2628         uint32_t level;
2629         uint32_t user_rid;
2630         union samr_UserInfo info;
2631         struct samr_CryptPassword pwd_buf;
2632         struct samr_CryptPasswordEx pwd_buf_ex;
2633         uint8_t nt_hash[16];
2634         uint8_t lm_hash[16];
2635         DATA_BLOB session_key;
2636         uint8_t password_expired = 0;
2637
2638         if (argc < 4) {
2639                 printf("Usage: %s username level password [password_expired]\n",
2640                         argv[0]);
2641                 return NT_STATUS_INVALID_PARAMETER;
2642         }
2643
2644         user = argv[1];
2645         level = atoi(argv[2]);
2646         param = argv[3];
2647
2648         if (argc >= 5) {
2649                 password_expired = atoi(argv[4]);
2650         }
2651
2652         status = cli_get_session_key(mem_ctx, cli, &session_key);
2653         if (!NT_STATUS_IS_OK(status)) {
2654                 return status;
2655         }
2656
2657         init_samr_CryptPassword(param, &session_key, &pwd_buf);
2658         init_samr_CryptPasswordEx(param, &session_key, &pwd_buf_ex);
2659         nt_lm_owf_gen(param, nt_hash, lm_hash);
2660
2661         switch (level) {
2662         case 18:
2663                 {
2664                         DATA_BLOB in,out;
2665                         in = data_blob_const(nt_hash, 16);
2666                         out = data_blob_talloc_zero(mem_ctx, 16);
2667                         sess_crypt_blob(&out, &in, &session_key, true);
2668                         memcpy(nt_hash, out.data, out.length);
2669                 }
2670                 {
2671                         DATA_BLOB in,out;
2672                         in = data_blob_const(lm_hash, 16);
2673                         out = data_blob_talloc_zero(mem_ctx, 16);
2674                         sess_crypt_blob(&out, &in, &session_key, true);
2675                         memcpy(lm_hash, out.data, out.length);
2676                 }
2677
2678                 memcpy(info.info18.nt_pwd.hash, nt_hash, 16);
2679                 memcpy(info.info18.lm_pwd.hash, lm_hash, 16);
2680                 info.info18.nt_pwd_active       = true;
2681                 info.info18.lm_pwd_active       = true;
2682                 info.info18.password_expired    = password_expired;
2683
2684                 break;
2685         case 21:
2686                 ZERO_STRUCT(info.info21);
2687
2688                 info.info21.fields_present = SAMR_FIELD_NT_PASSWORD_PRESENT |
2689                                              SAMR_FIELD_LM_PASSWORD_PRESENT;
2690                 if (argc >= 5) {
2691                         info.info21.fields_present |= SAMR_FIELD_EXPIRED_FLAG;
2692                         info.info21.password_expired = password_expired;
2693                 }
2694
2695                 info.info21.lm_password_set = true;
2696                 info.info21.lm_owf_password.length = 16;
2697                 info.info21.lm_owf_password.size = 16;
2698
2699                 info.info21.nt_password_set = true;
2700                 info.info21.nt_owf_password.length = 16;
2701                 info.info21.nt_owf_password.size = 16;
2702
2703                 {
2704                         DATA_BLOB in,out;
2705                         in = data_blob_const(nt_hash, 16);
2706                         out = data_blob_talloc_zero(mem_ctx, 16);
2707                         sess_crypt_blob(&out, &in, &session_key, true);
2708                         info.info21.nt_owf_password.array =
2709                                 (uint16_t *)talloc_memdup(mem_ctx, out.data, 16);
2710                 }
2711                 {
2712                         DATA_BLOB in,out;
2713                         in = data_blob_const(lm_hash, 16);
2714                         out = data_blob_talloc_zero(mem_ctx, 16);
2715                         sess_crypt_blob(&out, &in, &session_key, true);
2716                         info.info21.lm_owf_password.array =
2717                                 (uint16_t *)talloc_memdup(mem_ctx, out.data, 16);
2718                 }
2719
2720                 break;
2721         case 23:
2722                 ZERO_STRUCT(info.info23);
2723
2724                 info.info23.info.fields_present = SAMR_FIELD_NT_PASSWORD_PRESENT |
2725                                                   SAMR_FIELD_LM_PASSWORD_PRESENT;
2726                 if (argc >= 5) {
2727                         info.info23.info.fields_present |= SAMR_FIELD_EXPIRED_FLAG;
2728                         info.info23.info.password_expired = password_expired;
2729                 }
2730
2731                 info.info23.password = pwd_buf;
2732
2733                 break;
2734         case 24:
2735                 info.info24.password            = pwd_buf;
2736                 info.info24.password_expired    = password_expired;
2737
2738                 break;
2739         case 25:
2740                 ZERO_STRUCT(info.info25);
2741
2742                 info.info25.info.fields_present = SAMR_FIELD_NT_PASSWORD_PRESENT |
2743                                                   SAMR_FIELD_LM_PASSWORD_PRESENT;
2744                 if (argc >= 5) {
2745                         info.info25.info.fields_present |= SAMR_FIELD_EXPIRED_FLAG;
2746                         info.info25.info.password_expired = password_expired;
2747                 }
2748
2749                 info.info25.password = pwd_buf_ex;
2750
2751                 break;
2752         case 26:
2753                 info.info26.password            = pwd_buf_ex;
2754                 info.info26.password_expired    = password_expired;
2755
2756                 break;
2757         default:
2758                 return NT_STATUS_INVALID_INFO_CLASS;
2759         }
2760
2761         /* Get sam policy handle */
2762
2763         status = rpccli_try_samr_connects(cli, mem_ctx,
2764                                           MAXIMUM_ALLOWED_ACCESS,
2765                                           &connect_pol);
2766
2767         if (!NT_STATUS_IS_OK(status))
2768                 goto done;
2769
2770         /* Get domain policy handle */
2771
2772         status = rpccli_samr_OpenDomain(cli, mem_ctx,
2773                                         &connect_pol,
2774                                         access_mask,
2775                                         &domain_sid,
2776                                         &domain_pol);
2777
2778         if (!NT_STATUS_IS_OK(status))
2779                 goto done;
2780
2781         user_rid = strtol(user, NULL, 0);
2782         if (user_rid) {
2783                 status = rpccli_samr_OpenUser(cli, mem_ctx,
2784                                               &domain_pol,
2785                                               access_mask,
2786                                               user_rid,
2787                                               &user_pol);
2788         }
2789
2790         if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER) ||
2791             (user_rid == 0)) {
2792
2793                 /* Probably this was a user name, try lookupnames */
2794                 struct samr_Ids rids, types;
2795                 struct lsa_String lsa_acct_name;
2796
2797                 init_lsa_String(&lsa_acct_name, user);
2798
2799                 status = rpccli_samr_LookupNames(cli, mem_ctx,
2800                                                  &domain_pol,
2801                                                  1,
2802                                                  &lsa_acct_name,
2803                                                  &rids,
2804                                                  &types);
2805                 if (!NT_STATUS_IS_OK(status)) {
2806                         return status;
2807                 }
2808
2809                 status = rpccli_samr_OpenUser(cli, mem_ctx,
2810                                               &domain_pol,
2811                                               access_mask,
2812                                               rids.ids[0],
2813                                               &user_pol);
2814                 if (!NT_STATUS_IS_OK(status)) {
2815                         return status;
2816                 }
2817         }
2818
2819         switch (opcode) {
2820         case NDR_SAMR_SETUSERINFO:
2821                 status = rpccli_samr_SetUserInfo(cli, mem_ctx,
2822                                                  &user_pol,
2823                                                  level,
2824                                                  &info);
2825                 break;
2826         case NDR_SAMR_SETUSERINFO2:
2827                 status = rpccli_samr_SetUserInfo2(cli, mem_ctx,
2828                                                   &user_pol,
2829                                                   level,
2830                                                   &info);
2831                 break;
2832         default:
2833                 return NT_STATUS_INVALID_PARAMETER;
2834         }
2835
2836  done:
2837         return status;
2838 }
2839
2840 static NTSTATUS cmd_samr_setuserinfo(struct rpc_pipe_client *cli,
2841                                      TALLOC_CTX *mem_ctx,
2842                                      int argc, const char **argv)
2843 {
2844         return cmd_samr_setuserinfo_int(cli, mem_ctx, argc, argv,
2845                                         NDR_SAMR_SETUSERINFO);
2846 }
2847
2848 static NTSTATUS cmd_samr_setuserinfo2(struct rpc_pipe_client *cli,
2849                                       TALLOC_CTX *mem_ctx,
2850                                       int argc, const char **argv)
2851 {
2852         return cmd_samr_setuserinfo_int(cli, mem_ctx, argc, argv,
2853                                         NDR_SAMR_SETUSERINFO2);
2854 }
2855
2856 static NTSTATUS cmd_samr_get_dispinfo_idx(struct rpc_pipe_client *cli,
2857                                           TALLOC_CTX *mem_ctx,
2858                                           int argc, const char **argv)
2859 {
2860         NTSTATUS status;
2861         struct policy_handle connect_handle;
2862         struct policy_handle domain_handle;
2863         uint16_t level = 1;
2864         struct lsa_String name;
2865         uint32_t idx = 0;
2866
2867         if (argc < 2 || argc > 3) {
2868                 printf("Usage: %s name level\n", argv[0]);
2869                 return NT_STATUS_INVALID_PARAMETER;
2870         }
2871
2872         init_lsa_String(&name, argv[1]);
2873
2874         if (argc == 3) {
2875                 level = atoi(argv[2]);
2876         }
2877
2878         status = rpccli_try_samr_connects(cli, mem_ctx,
2879                                           SEC_FLAG_MAXIMUM_ALLOWED,
2880                                           &connect_handle);
2881
2882         if (!NT_STATUS_IS_OK(status)) {
2883                 goto done;
2884         }
2885
2886         status = rpccli_samr_OpenDomain(cli, mem_ctx,
2887                                         &connect_handle,
2888                                         SEC_FLAG_MAXIMUM_ALLOWED,
2889                                         &domain_sid,
2890                                         &domain_handle);
2891
2892         if (!NT_STATUS_IS_OK(status))
2893                 goto done;
2894
2895
2896         status = rpccli_samr_GetDisplayEnumerationIndex(cli, mem_ctx,
2897                                                         &domain_handle,
2898                                                         level,
2899                                                         &name,
2900                                                         &idx);
2901
2902         if (NT_STATUS_IS_OK(status) ||
2903             NT_STATUS_EQUAL(status, NT_STATUS_NO_MORE_ENTRIES)) {
2904                 printf("idx: %d (0x%08x)\n", idx, idx);
2905         }
2906  done:
2907
2908         if (is_valid_policy_hnd(&domain_handle)) {
2909                 rpccli_samr_Close(cli, mem_ctx, &domain_handle);
2910         }
2911         if (is_valid_policy_hnd(&connect_handle)) {
2912                 rpccli_samr_Close(cli, mem_ctx, &connect_handle);
2913         }
2914
2915         return status;
2916
2917 }
2918 /* List of commands exported by this module */
2919
2920 struct cmd_set samr_commands[] = {
2921
2922         { "SAMR" },
2923
2924         { "queryuser",  RPC_RTYPE_NTSTATUS, cmd_samr_query_user,                NULL, &ndr_table_samr.syntax_id, NULL,  "Query user info",         "" },
2925         { "querygroup",         RPC_RTYPE_NTSTATUS, cmd_samr_query_group,               NULL, &ndr_table_samr.syntax_id, NULL,  "Query group info",        "" },
2926         { "queryusergroups",    RPC_RTYPE_NTSTATUS, cmd_samr_query_usergroups,  NULL, &ndr_table_samr.syntax_id, NULL,  "Query user groups",       "" },
2927         { "queryuseraliases",   RPC_RTYPE_NTSTATUS, cmd_samr_query_useraliases,         NULL, &ndr_table_samr.syntax_id, NULL,  "Query user aliases",      "" },
2928         { "querygroupmem",      RPC_RTYPE_NTSTATUS, cmd_samr_query_groupmem,    NULL, &ndr_table_samr.syntax_id, NULL,  "Query group membership",  "" },
2929         { "queryaliasmem",      RPC_RTYPE_NTSTATUS, cmd_samr_query_aliasmem,    NULL, &ndr_table_samr.syntax_id, NULL,  "Query alias membership",  "" },
2930         { "queryaliasinfo",     RPC_RTYPE_NTSTATUS, cmd_samr_query_aliasinfo,   NULL, &ndr_table_samr.syntax_id, NULL,  "Query alias info",       "" },
2931         { "deletealias",        RPC_RTYPE_NTSTATUS, cmd_samr_delete_alias,      NULL, &ndr_table_samr.syntax_id, NULL,  "Delete an alias",  "" },
2932         { "querydispinfo",      RPC_RTYPE_NTSTATUS, cmd_samr_query_dispinfo,    NULL, &ndr_table_samr.syntax_id, NULL,  "Query display info",      "" },
2933         { "querydispinfo2",     RPC_RTYPE_NTSTATUS, cmd_samr_query_dispinfo2,   NULL, &ndr_table_samr.syntax_id, NULL,  "Query display info",      "" },
2934         { "querydispinfo3",     RPC_RTYPE_NTSTATUS, cmd_samr_query_dispinfo3,   NULL, &ndr_table_samr.syntax_id, NULL,  "Query display info",      "" },
2935         { "querydominfo",       RPC_RTYPE_NTSTATUS, cmd_samr_query_dominfo,     NULL, &ndr_table_samr.syntax_id, NULL,  "Query domain info",       "" },
2936         { "enumdomusers",       RPC_RTYPE_NTSTATUS, cmd_samr_enum_dom_users,       NULL, &ndr_table_samr.syntax_id, NULL,       "Enumerate domain users", "" },
2937         { "enumdomgroups",      RPC_RTYPE_NTSTATUS, cmd_samr_enum_dom_groups,       NULL, &ndr_table_samr.syntax_id, NULL,      "Enumerate domain groups", "" },
2938         { "enumalsgroups",      RPC_RTYPE_NTSTATUS, cmd_samr_enum_als_groups,       NULL, &ndr_table_samr.syntax_id, NULL,      "Enumerate alias groups",  "" },
2939         { "enumdomains",        RPC_RTYPE_NTSTATUS, cmd_samr_enum_domains,          NULL, &ndr_table_samr.syntax_id, NULL,      "Enumerate domains",  "" },
2940
2941         { "createdomuser",      RPC_RTYPE_NTSTATUS, cmd_samr_create_dom_user,       NULL, &ndr_table_samr.syntax_id, NULL,      "Create domain user",      "" },
2942         { "createdomgroup",     RPC_RTYPE_NTSTATUS, cmd_samr_create_dom_group,      NULL, &ndr_table_samr.syntax_id, NULL,      "Create domain group",     "" },
2943         { "createdomalias",     RPC_RTYPE_NTSTATUS, cmd_samr_create_dom_alias,      NULL, &ndr_table_samr.syntax_id, NULL,      "Create domain alias",     "" },
2944         { "samlookupnames",     RPC_RTYPE_NTSTATUS, cmd_samr_lookup_names,          NULL, &ndr_table_samr.syntax_id, NULL,      "Look up names",           "" },
2945         { "samlookuprids",      RPC_RTYPE_NTSTATUS, cmd_samr_lookup_rids,           NULL, &ndr_table_samr.syntax_id, NULL,      "Look up names",           "" },
2946         { "deletedomgroup",     RPC_RTYPE_NTSTATUS, cmd_samr_delete_dom_group,      NULL, &ndr_table_samr.syntax_id, NULL,      "Delete domain group",     "" },
2947         { "deletedomuser",      RPC_RTYPE_NTSTATUS, cmd_samr_delete_dom_user,       NULL, &ndr_table_samr.syntax_id, NULL,      "Delete domain user",      "" },
2948         { "samquerysecobj",     RPC_RTYPE_NTSTATUS, cmd_samr_query_sec_obj,         NULL, &ndr_table_samr.syntax_id, NULL, "Query SAMR security object",   "" },
2949         { "getdompwinfo",       RPC_RTYPE_NTSTATUS, cmd_samr_get_dom_pwinfo,        NULL, &ndr_table_samr.syntax_id, NULL, "Retrieve domain password info", "" },
2950         { "getusrdompwinfo",    RPC_RTYPE_NTSTATUS, cmd_samr_get_usrdom_pwinfo,     NULL, &ndr_table_samr.syntax_id, NULL, "Retrieve user domain password info", "" },
2951
2952         { "lookupdomain",       RPC_RTYPE_NTSTATUS, cmd_samr_lookup_domain,         NULL, &ndr_table_samr.syntax_id, NULL, "Lookup Domain Name", "" },
2953         { "chgpasswd",          RPC_RTYPE_NTSTATUS, cmd_samr_chgpasswd,             NULL, &ndr_table_samr.syntax_id, NULL, "Change user password", "" },
2954         { "chgpasswd2",         RPC_RTYPE_NTSTATUS, cmd_samr_chgpasswd2,            NULL, &ndr_table_samr.syntax_id, NULL, "Change user password", "" },
2955         { "chgpasswd3",         RPC_RTYPE_NTSTATUS, cmd_samr_chgpasswd3,            NULL, &ndr_table_samr.syntax_id, NULL, "Change user password", "" },
2956         { "getdispinfoidx",     RPC_RTYPE_NTSTATUS, cmd_samr_get_dispinfo_idx,      NULL, &ndr_table_samr.syntax_id, NULL, "Get Display Information Index", "" },
2957         { "setuserinfo",        RPC_RTYPE_NTSTATUS, cmd_samr_setuserinfo,           NULL, &ndr_table_samr.syntax_id, NULL, "Set user info", "" },
2958         { "setuserinfo2",       RPC_RTYPE_NTSTATUS, cmd_samr_setuserinfo2,          NULL, &ndr_table_samr.syntax_id, NULL, "Set user info2", "" },
2959         { NULL }
2960 };