r13523: Fix indent.
[samba.git] / source3 / rpcclient / cmd_samr.c
1 /* 
2    Unix SMB/CIFS implementation.
3    RPC pipe client
4
5    Copyright (C) Andrew Tridgell              1992-2000,
6    Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
7    Copyright (C) Elrond                            2000,
8    Copyright (C) Tim Potter                        2000
9
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 2 of the License, or
13    (at your option) any later version.
14    
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19    
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 */
24
25 #include "includes.h"
26 #include "rpcclient.h"
27
28 extern DOM_SID domain_sid;
29
30 /****************************************************************************
31  display sam_user_info_7 structure
32  ****************************************************************************/
33 static void display_sam_user_info_7(SAM_USER_INFO_7 *usr)
34 {
35         fstring temp;
36
37         unistr2_to_ascii(temp, &usr->uni_name, sizeof(temp)-1);
38         printf("\tUser Name   :\t%s\n", temp);
39 }
40
41 /****************************************************************************
42  display sam_user_info_9 structure
43  ****************************************************************************/
44 static void display_sam_user_info_9(SAM_USER_INFO_9 *usr)
45 {
46         printf("\tPrimary group RID   :\tox%x\n", usr->rid_group);
47 }
48
49 /****************************************************************************
50  display sam_user_info_21 structure
51  ****************************************************************************/
52 static void display_sam_user_info_21(SAM_USER_INFO_21 *usr)
53 {
54         fstring temp;
55
56         unistr2_to_ascii(temp, &usr->uni_user_name, sizeof(temp)-1);
57         printf("\tUser Name   :\t%s\n", temp);
58         
59         unistr2_to_ascii(temp, &usr->uni_full_name, sizeof(temp)-1);
60         printf("\tFull Name   :\t%s\n", temp);
61         
62         unistr2_to_ascii(temp, &usr->uni_home_dir, sizeof(temp)-1);
63         printf("\tHome Drive  :\t%s\n", temp);
64         
65         unistr2_to_ascii(temp, &usr->uni_dir_drive, sizeof(temp)-1);
66         printf("\tDir Drive   :\t%s\n", temp);
67         
68         unistr2_to_ascii(temp, &usr->uni_profile_path, sizeof(temp)-1);
69         printf("\tProfile Path:\t%s\n", temp);
70         
71         unistr2_to_ascii(temp, &usr->uni_logon_script, sizeof(temp)-1);
72         printf("\tLogon Script:\t%s\n", temp);
73         
74         unistr2_to_ascii(temp, &usr->uni_acct_desc, sizeof(temp)-1);
75         printf("\tDescription :\t%s\n", temp);
76         
77         unistr2_to_ascii(temp, &usr->uni_workstations, sizeof(temp)-1);
78         printf("\tWorkstations:\t%s\n", temp);
79         
80         unistr2_to_ascii(temp, &usr->uni_unknown_str, sizeof(temp)-1);
81         printf("\tUnknown Str :\t%s\n", temp);
82         
83         unistr2_to_ascii(temp, &usr->uni_munged_dial, sizeof(temp)-1);
84         printf("\tRemote Dial :\t%s\n", temp);
85         
86         printf("\tLogon Time               :\t%s\n", 
87                http_timestring(nt_time_to_unix(&usr->logon_time)));
88         printf("\tLogoff Time              :\t%s\n", 
89                http_timestring(nt_time_to_unix(&usr->logoff_time)));
90         printf("\tKickoff Time             :\t%s\n", 
91                http_timestring(nt_time_to_unix(&usr->kickoff_time)));
92         printf("\tPassword last set Time   :\t%s\n", 
93                http_timestring(nt_time_to_unix(&usr->pass_last_set_time)));
94         printf("\tPassword can change Time :\t%s\n", 
95                http_timestring(nt_time_to_unix(&usr->pass_can_change_time)));
96         printf("\tPassword must change Time:\t%s\n", 
97                http_timestring(nt_time_to_unix(&usr->pass_must_change_time)));
98         
99         printf("\tunknown_2[0..31]...\n"); /* user passwords? */
100         
101         printf("\tuser_rid :\t0x%x\n"  , usr->user_rid ); /* User ID */
102         printf("\tgroup_rid:\t0x%x\n"  , usr->group_rid); /* Group ID */
103         printf("\tacb_info :\t0x%04x\n", usr->acb_info ); /* Account Control Info */
104         
105         printf("\tfields_present:\t0x%08x\n", usr->fields_present); /* 0x00ff ffff */
106         printf("\tlogon_divs:\t%d\n", usr->logon_divs); /* 0x0000 00a8 which is 168 which is num hrs in a week */
107         printf("\tbad_password_count:\t0x%08x\n", usr->bad_password_count);
108         printf("\tlogon_count:\t0x%08x\n", usr->logon_count);
109         
110         printf("\tpadding1[0..7]...\n");
111         
112         if (usr->ptr_logon_hrs) {
113                 printf("\tlogon_hrs[0..%d]...\n", usr->logon_hrs.len);
114         }
115 }
116
117 static const char *display_time(NTTIME nttime)
118 {
119         static fstring string;
120
121         float high;
122         float low;
123         int sec;
124         int days, hours, mins, secs;
125
126         if (nttime.high==0 && nttime.low==0)
127                 return "Now";
128
129         if (nttime.high==0x80000000 && nttime.low==0)
130                 return "Never";
131
132         high = 65536;   
133         high = high/10000;
134         high = high*65536;
135         high = high/1000;
136         high = high * (~nttime.high);
137
138         low = ~nttime.low;      
139         low = low/(1000*1000*10);
140
141         sec=high+low;
142
143         days=sec/(60*60*24);
144         hours=(sec - (days*60*60*24)) / (60*60);
145         mins=(sec - (days*60*60*24) - (hours*60*60) ) / 60;
146         secs=sec - (days*60*60*24) - (hours*60*60) - (mins*60);
147
148         fstr_sprintf(string, "%u days, %u hours, %u minutes, %u seconds", days, hours, mins, secs);
149         return (string);
150 }
151
152 static void display_password_properties(uint32 password_properties) 
153 {
154         printf("password_properties: 0x%08x\n", password_properties);
155                 
156         if (password_properties & DOMAIN_PASSWORD_COMPLEX)
157                 printf("\tDOMAIN_PASSWORD_COMPLEX\n");
158                         
159         if (password_properties & DOMAIN_PASSWORD_NO_ANON_CHANGE)
160                 printf("\tDOMAIN_PASSWORD_NO_ANON_CHANGE\n");
161                         
162         if (password_properties & DOMAIN_PASSWORD_NO_CLEAR_CHANGE)
163                 printf("\tDOMAIN_PASSWORD_NO_CLEAR_CHANGE\n");
164                         
165         if (password_properties & DOMAIN_LOCKOUT_ADMINS)
166                 printf("\tDOMAIN_LOCKOUT_ADMINS\n");
167                         
168         if (password_properties & DOMAIN_PASSWORD_STORE_CLEARTEXT)
169                 printf("\tDOMAIN_PASSWORD_STORE_CLEARTEXT\n");
170                         
171         if (password_properties & DOMAIN_REFUSE_PASSWORD_CHANGE)
172                 printf("\tDOMAIN_REFUSE_PASSWORD_CHANGE\n");
173 }
174
175 static void display_sam_unk_info_1(SAM_UNK_INFO_1 *info1)
176 {
177         
178         printf("Minimum password length:\t\t\t%d\n", info1->min_length_password);
179         printf("Password uniqueness (remember x passwords):\t%d\n", info1->password_history);
180         display_password_properties(info1->password_properties);
181         printf("password expire in:\t\t\t\t%s\n", display_time(info1->expire));
182         printf("Min password age (allow changing in x days):\t%s\n", display_time(info1->min_passwordage));
183 }
184
185 static void display_sam_unk_info_2(SAM_UNK_INFO_2 *info2)
186 {
187         fstring name;
188
189         unistr2_to_ascii(name, &info2->uni_domain, sizeof(name) - 1); 
190         printf("Domain:\t\t%s\n", name);
191
192         unistr2_to_ascii(name, &info2->uni_server, sizeof(name) - 1); 
193         printf("Server:\t\t%s\n", name);
194
195         unistr2_to_ascii(name, &info2->uni_comment, sizeof(name) - 1); 
196         printf("Comment:\t%s\n", name);
197
198         printf("Total Users:\t%d\n", info2->num_domain_usrs);
199         printf("Total Groups:\t%d\n", info2->num_domain_grps);
200         printf("Total Aliases:\t%d\n", info2->num_local_grps);
201         
202         printf("Sequence No:\t%d\n", info2->seq_num.low);
203
204         printf("Force Logoff:\t%d\n", (int)nt_time_to_unix_abs(&info2->logout));
205
206         printf("Unknown 4:\t0x%x\n", info2->unknown_4);
207         printf("Server Role:\t%s\n", server_role_str(info2->server_role));
208         printf("Unknown 6:\t0x%x\n", info2->unknown_6);
209 }
210
211 static void display_sam_unk_info_7(SAM_UNK_INFO_7 *info7)
212 {
213         printf("Server Role:\t%s\n", server_role_str(info7->server_role));
214 }
215
216 static void display_sam_unk_info_8(SAM_UNK_INFO_8 *info8)
217 {
218         printf("Sequence No:\t%d\n", info8->seq_num.low);
219         printf("Domain Create Time:\t%s\n", 
220                 http_timestring(nt_time_to_unix(&info8->domain_create_time)));
221
222 }
223
224 static void display_sam_unk_info_12(SAM_UNK_INFO_12 *info12)
225 {
226         printf("Bad password lockout duration:               %s\n", display_time(info12->duration));
227         printf("Reset Lockout after:                         %s\n", display_time(info12->reset_count));
228         printf("Lockout after bad attempts:                  %d\n", info12->bad_attempt_lockout);
229 }
230
231 static void display_sam_info_1(SAM_ENTRY1 *e1, SAM_STR1 *s1)
232 {
233         fstring tmp;
234
235         printf("index: 0x%x ", e1->user_idx);
236         printf("RID: 0x%x ", e1->rid_user);
237         printf("acb: 0x%x ", e1->acb_info);
238
239         unistr2_to_ascii(tmp, &s1->uni_acct_name, sizeof(tmp)-1);
240         printf("Account: %s\t", tmp);
241
242         unistr2_to_ascii(tmp, &s1->uni_full_name, sizeof(tmp)-1);
243         printf("Name: %s\t", tmp);
244
245         unistr2_to_ascii(tmp, &s1->uni_acct_desc, sizeof(tmp)-1);
246         printf("Desc: %s\n", tmp);
247 }
248
249 static void display_sam_info_2(SAM_ENTRY2 *e2, SAM_STR2 *s2)
250 {
251         fstring tmp;
252
253         printf("index: 0x%x ", e2->user_idx);
254         printf("RID: 0x%x ", e2->rid_user);
255         printf("acb: 0x%x ", e2->acb_info);
256         
257         unistr2_to_ascii(tmp, &s2->uni_srv_name, sizeof(tmp)-1);
258         printf("Account: %s\t", tmp);
259
260         unistr2_to_ascii(tmp, &s2->uni_srv_desc, sizeof(tmp)-1);
261         printf("Name: %s\n", tmp);
262
263 }
264
265 static void display_sam_info_3(SAM_ENTRY3 *e3, SAM_STR3 *s3)
266 {
267         fstring tmp;
268
269         printf("index: 0x%x ", e3->grp_idx);
270         printf("RID: 0x%x ", e3->rid_grp);
271         printf("attr: 0x%x ", e3->attr);
272         
273         unistr2_to_ascii(tmp, &s3->uni_grp_name, sizeof(tmp)-1);
274         printf("Account: %s\t", tmp);
275
276         unistr2_to_ascii(tmp, &s3->uni_grp_desc, sizeof(tmp)-1);
277         printf("Name: %s\n", tmp);
278
279 }
280
281 static void display_sam_info_4(SAM_ENTRY4 *e4, SAM_STR4 *s4)
282 {
283         int i;
284
285         printf("index: %d ", e4->user_idx);
286         
287         printf("Account: ");
288         for (i=0; i<s4->acct_name.str_str_len; i++)
289                 printf("%c", s4->acct_name.buffer[i]);
290         printf("\n");
291
292 }
293
294 static void display_sam_info_5(SAM_ENTRY5 *e5, SAM_STR5 *s5)
295 {
296         int i;
297
298         printf("index: 0x%x ", e5->grp_idx);
299         
300         printf("Account: ");
301         for (i=0; i<s5->grp_name.str_str_len; i++)
302                 printf("%c", s5->grp_name.buffer[i]);
303         printf("\n");
304
305 }
306
307 /****************************************************************************
308  Try samr_connect4 first, then samr_conenct if it fails
309  ****************************************************************************/
310 static NTSTATUS try_samr_connects(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, 
311                                   uint32 access_mask, POLICY_HND *connect_pol)
312 {
313         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
314         
315         result = rpccli_samr_connect4(cli, mem_ctx, access_mask, connect_pol);
316         if (!NT_STATUS_IS_OK(result)) {
317                 result = rpccli_samr_connect(cli, mem_ctx, access_mask,
318                                           connect_pol);
319         }
320         return result;
321 }
322
323 /**********************************************************************
324  * Query user information 
325  */
326 static NTSTATUS cmd_samr_query_user(struct rpc_pipe_client *cli, 
327                                     TALLOC_CTX *mem_ctx,
328                                     int argc, const char **argv) 
329 {
330         POLICY_HND connect_pol, domain_pol, user_pol;
331         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
332         uint32 info_level = 21;
333         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
334         SAM_USERINFO_CTR *user_ctr;
335         fstring server;
336         uint32 user_rid;
337         
338         if ((argc < 2) || (argc > 4)) {
339                 printf("Usage: %s rid [info level] [access mask] \n", argv[0]);
340                 return NT_STATUS_OK;
341         }
342         
343         user_rid = strtoul(argv[1], NULL, 10);
344         
345         if (argc > 2)
346                 sscanf(argv[2], "%i", &info_level);
347                 
348         if (argc > 3)
349                 sscanf(argv[3], "%x", &access_mask);
350         
351
352         slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost);
353         strupper_m(server);
354         
355         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
356                                    &connect_pol);
357
358         if (!NT_STATUS_IS_OK(result))
359                 goto done;
360
361         result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
362                                       MAXIMUM_ALLOWED_ACCESS,
363                                       &domain_sid, &domain_pol);
364
365         if (!NT_STATUS_IS_OK(result))
366                 goto done;
367
368         result = rpccli_samr_open_user(cli, mem_ctx, &domain_pol,
369                                     access_mask,
370                                     user_rid, &user_pol);
371
372         if (NT_STATUS_EQUAL(result, NT_STATUS_NO_SUCH_USER) &&
373             (user_rid == 0)) {
374
375                 /* Probably this was a user name, try lookupnames */
376                 uint32 num_rids;
377                 uint32 *rids, *types;
378                 
379                 result = rpccli_samr_lookup_names(cli, mem_ctx, &domain_pol,
380                                                   1000, 1, &argv[1],
381                                                   &num_rids, &rids,
382                                                   &types);
383
384                 if (NT_STATUS_IS_OK(result)) {
385                         result = rpccli_samr_open_user(cli, mem_ctx,
386                                                        &domain_pol,
387                                                        access_mask,
388                                                        rids[0], &user_pol);
389                 }
390         }
391
392
393         if (!NT_STATUS_IS_OK(result))
394                 goto done;
395
396         ZERO_STRUCT(user_ctr);
397
398         result = rpccli_samr_query_userinfo(cli, mem_ctx, &user_pol, 
399                                          info_level, &user_ctr);
400
401         if (!NT_STATUS_IS_OK(result))
402                 goto done;
403
404         switch (user_ctr->switch_value) {
405         case 21:
406                 display_sam_user_info_21(user_ctr->info.id21);
407                 break;
408         case 7:
409                 display_sam_user_info_7(user_ctr->info.id7);
410                 break;
411         case 9:
412                 display_sam_user_info_9(user_ctr->info.id9);
413                 break;
414         default:
415                 printf("Unsupported infolevel: %d\n", info_level);
416                 break;
417         }
418
419         rpccli_samr_close(cli, mem_ctx, &user_pol);
420         rpccli_samr_close(cli, mem_ctx, &domain_pol);
421         rpccli_samr_close(cli, mem_ctx, &connect_pol);
422
423 done:
424         return result;
425 }
426
427 /****************************************************************************
428  display group info
429  ****************************************************************************/
430 static void display_group_info1(GROUP_INFO1 *info1)
431 {
432         fstring temp;
433
434         unistr2_to_ascii(temp, &info1->uni_acct_name, sizeof(temp)-1);
435         printf("\tGroup Name:\t%s\n", temp);
436         unistr2_to_ascii(temp, &info1->uni_acct_desc, sizeof(temp)-1);
437         printf("\tDescription:\t%s\n", temp);
438         printf("\tGroup Attribute:%d\n", info1->group_attr);
439         printf("\tNum Members:%d\n", info1->num_members);
440 }
441
442 /****************************************************************************
443  display group info
444  ****************************************************************************/
445 static void display_group_info3(GROUP_INFO3 *info3)
446 {
447         printf("\tGroup Attribute:%d\n", info3->group_attr);
448 }
449
450
451 /****************************************************************************
452  display group info
453  ****************************************************************************/
454 static void display_group_info4(GROUP_INFO4 *info4)
455 {
456         fstring desc;
457
458         unistr2_to_ascii(desc, &info4->uni_acct_desc, sizeof(desc)-1);
459         printf("\tGroup Description:%s\n", desc);
460 }
461
462 /****************************************************************************
463  display sam sync structure
464  ****************************************************************************/
465 static void display_group_info_ctr(GROUP_INFO_CTR *ctr)
466 {
467         switch (ctr->switch_value1) {
468             case 1: {
469                     display_group_info1(&ctr->group.info1);
470                     break;
471             }
472             case 3: {
473                     display_group_info3(&ctr->group.info3);
474                     break;
475             }
476             case 4: {
477                     display_group_info4(&ctr->group.info4);
478                     break;
479             }
480         }
481 }
482
483 /***********************************************************************
484  * Query group information 
485  */
486 static NTSTATUS cmd_samr_query_group(struct rpc_pipe_client *cli, 
487                                      TALLOC_CTX *mem_ctx,
488                                      int argc, const char **argv) 
489 {
490         POLICY_HND connect_pol, domain_pol, group_pol;
491         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
492         uint32 info_level = 1;
493         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
494         GROUP_INFO_CTR *group_ctr;
495         fstring                 server; 
496         uint32 group_rid;
497         
498         if ((argc < 2) || (argc > 4)) {
499                 printf("Usage: %s rid [info level] [access mask]\n", argv[0]);
500                 return NT_STATUS_OK;
501         }
502
503         sscanf(argv[1], "%i", &group_rid);
504         
505         if (argc > 2)
506                 sscanf(argv[2], "%i", &info_level);
507         
508         if (argc > 3)
509                 sscanf(argv[3], "%x", &access_mask);
510
511         slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost);
512         strupper_m(server);
513
514         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
515                                    &connect_pol);
516
517         if (!NT_STATUS_IS_OK(result))
518                 goto done;
519
520         result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
521                                       MAXIMUM_ALLOWED_ACCESS,
522                                       &domain_sid, &domain_pol);
523
524         if (!NT_STATUS_IS_OK(result))
525                 goto done;
526
527         result = rpccli_samr_open_group(cli, mem_ctx, &domain_pol,
528                                      access_mask,
529                                      group_rid, &group_pol);
530
531         if (!NT_STATUS_IS_OK(result))
532                 goto done;
533
534         result = rpccli_samr_query_groupinfo(cli, mem_ctx, &group_pol, 
535                                           info_level, &group_ctr);
536         if (!NT_STATUS_IS_OK(result)) {
537                 goto done;
538         }
539
540         display_group_info_ctr(group_ctr);
541
542         rpccli_samr_close(cli, mem_ctx, &group_pol);
543         rpccli_samr_close(cli, mem_ctx, &domain_pol);
544         rpccli_samr_close(cli, mem_ctx, &connect_pol);
545 done:
546         return result;
547 }
548
549 /* Query groups a user is a member of */
550
551 static NTSTATUS cmd_samr_query_usergroups(struct rpc_pipe_client *cli, 
552                                           TALLOC_CTX *mem_ctx,
553                                           int argc, const char **argv) 
554 {
555         POLICY_HND              connect_pol, 
556                                 domain_pol, 
557                                 user_pol;
558         NTSTATUS                result = NT_STATUS_UNSUCCESSFUL;
559         uint32                  num_groups, 
560                                 user_rid;
561         uint32                  access_mask = MAXIMUM_ALLOWED_ACCESS;
562         DOM_GID                 *user_gids;
563         int                     i;
564         fstring                 server;
565         
566         if ((argc < 2) || (argc > 3)) {
567                 printf("Usage: %s rid [access mask]\n", argv[0]);
568                 return NT_STATUS_OK;
569         }
570
571         sscanf(argv[1], "%i", &user_rid);
572         
573         if (argc > 2)
574                 sscanf(argv[2], "%x", &access_mask);
575
576         slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost);
577         strupper_m(server);
578                 
579         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
580                                    &connect_pol);
581
582         if (!NT_STATUS_IS_OK(result))
583                 goto done;
584
585         result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
586                                       MAXIMUM_ALLOWED_ACCESS,
587                                       &domain_sid, &domain_pol);
588
589         if (!NT_STATUS_IS_OK(result))
590                 goto done;
591
592         result = rpccli_samr_open_user(cli, mem_ctx, &domain_pol,
593                                     access_mask,
594                                     user_rid, &user_pol);
595
596         if (!NT_STATUS_IS_OK(result))
597                 goto done;
598
599         result = rpccli_samr_query_usergroups(cli, mem_ctx, &user_pol,
600                                            &num_groups, &user_gids);
601
602         if (!NT_STATUS_IS_OK(result))
603                 goto done;
604
605         for (i = 0; i < num_groups; i++) {
606                 printf("\tgroup rid:[0x%x] attr:[0x%x]\n", 
607                        user_gids[i].g_rid, user_gids[i].attr);
608         }
609
610         rpccli_samr_close(cli, mem_ctx, &user_pol);
611         rpccli_samr_close(cli, mem_ctx, &domain_pol);
612         rpccli_samr_close(cli, mem_ctx, &connect_pol);
613  done:
614         return result;
615 }
616
617 /* Query aliases a user is a member of */
618
619 static NTSTATUS cmd_samr_query_useraliases(struct rpc_pipe_client *cli, 
620                                            TALLOC_CTX *mem_ctx,
621                                            int argc, const char **argv) 
622 {
623         POLICY_HND              connect_pol, domain_pol;
624         NTSTATUS                result = NT_STATUS_UNSUCCESSFUL;
625         DOM_SID                *sids;
626         size_t                     num_sids;
627         uint32                  num_aliases, *alias_rids;
628         uint32                  access_mask = MAXIMUM_ALLOWED_ACCESS;
629         int                     i;
630         fstring                 server;
631         DOM_SID2               *sid2;
632
633         if (argc < 3) {
634                 printf("Usage: %s builtin|domain sid1 sid2 ...\n", argv[0]);
635                 return NT_STATUS_INVALID_PARAMETER;
636         }
637
638         sids = NULL;
639         num_sids = 0;
640
641         for (i=2; i<argc; i++) {
642                 DOM_SID tmp_sid;
643                 if (!string_to_sid(&tmp_sid, argv[i])) {
644                         printf("%s is not a legal SID\n", argv[i]);
645                         return NT_STATUS_INVALID_PARAMETER;
646                 }
647                 add_sid_to_array(mem_ctx, &tmp_sid, &sids, &num_sids);
648         }
649
650         sid2 = TALLOC_ARRAY(mem_ctx, DOM_SID2, num_sids);
651         if (sid2 == NULL)
652                 return NT_STATUS_NO_MEMORY;
653
654         for (i=0; i<num_sids; i++) {
655                 sid_copy(&sid2[i].sid, &sids[i]);
656                 sid2[i].num_auths = sid2[i].sid.num_auths;
657         }
658
659         slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost);
660         strupper_m(server);
661                 
662         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
663                                    &connect_pol);
664
665         if (!NT_STATUS_IS_OK(result))
666                 goto done;
667
668         if (StrCaseCmp(argv[1], "domain")==0)
669                 result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
670                                               access_mask,
671                                               &domain_sid, &domain_pol);
672         else if (StrCaseCmp(argv[1], "builtin")==0)
673                 result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
674                                               access_mask,
675                                               &global_sid_Builtin,
676                                               &domain_pol);
677         else {
678                 printf("Usage: %s builtin|domain sid1 sid2 ...\n", argv[0]);
679                 return NT_STATUS_INVALID_PARAMETER;
680         }
681
682         if (!NT_STATUS_IS_OK(result))
683                 goto done;
684
685         result = rpccli_samr_query_useraliases(cli, mem_ctx, &domain_pol,
686                                             num_sids, sid2,
687                                             &num_aliases, &alias_rids);
688
689         if (!NT_STATUS_IS_OK(result))
690                 goto done;
691
692         for (i = 0; i < num_aliases; i++) {
693                 printf("\tgroup rid:[0x%x]\n", alias_rids[i]);
694         }
695
696         rpccli_samr_close(cli, mem_ctx, &domain_pol);
697         rpccli_samr_close(cli, mem_ctx, &connect_pol);
698  done:
699         return result;
700 }
701
702 /* Query members of a group */
703
704 static NTSTATUS cmd_samr_query_groupmem(struct rpc_pipe_client *cli, 
705                                         TALLOC_CTX *mem_ctx,
706                                         int argc, const char **argv) 
707 {
708         POLICY_HND connect_pol, domain_pol, group_pol;
709         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
710         uint32 num_members, *group_rids, *group_attrs, group_rid;
711         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
712         int i;
713         fstring                 server;
714         
715         if ((argc < 2) || (argc > 3)) {
716                 printf("Usage: %s rid [access mask]\n", argv[0]);
717                 return NT_STATUS_OK;
718         }
719
720         sscanf(argv[1], "%i", &group_rid);
721         
722         if (argc > 2)
723                 sscanf(argv[2], "%x", &access_mask);
724
725         slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost);
726         strupper_m(server);
727
728         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
729                                    &connect_pol);
730
731         if (!NT_STATUS_IS_OK(result))
732                 goto done;
733
734         result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
735                                       MAXIMUM_ALLOWED_ACCESS,
736                                       &domain_sid, &domain_pol);
737
738         if (!NT_STATUS_IS_OK(result))
739                 goto done;
740
741         result = rpccli_samr_open_group(cli, mem_ctx, &domain_pol,
742                                      access_mask,
743                                      group_rid, &group_pol);
744
745         if (!NT_STATUS_IS_OK(result))
746                 goto done;
747
748         result = rpccli_samr_query_groupmem(cli, mem_ctx, &group_pol,
749                                          &num_members, &group_rids,
750                                          &group_attrs);
751
752         if (!NT_STATUS_IS_OK(result))
753                 goto done;
754
755         for (i = 0; i < num_members; i++) {
756                 printf("\trid:[0x%x] attr:[0x%x]\n", group_rids[i],
757                        group_attrs[i]);
758         }
759
760         rpccli_samr_close(cli, mem_ctx, &group_pol);
761         rpccli_samr_close(cli, mem_ctx, &domain_pol);
762         rpccli_samr_close(cli, mem_ctx, &connect_pol);
763  done:
764         return result;
765 }
766
767 /* Enumerate domain users */
768
769 static NTSTATUS cmd_samr_enum_dom_users(struct rpc_pipe_client *cli, 
770                                         TALLOC_CTX *mem_ctx,
771                                         int argc, const char **argv) 
772 {
773         POLICY_HND connect_pol, domain_pol;
774         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
775         uint32 start_idx, size, num_dom_users, i;
776         char **dom_users;
777         uint32 *dom_rids;
778         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
779         uint16 acb_mask = ACB_NORMAL;
780         BOOL got_connect_pol = False, got_domain_pol = False;
781
782         if ((argc < 1) || (argc > 3)) {
783                 printf("Usage: %s [access_mask] [acb_mask]\n", argv[0]);
784                 return NT_STATUS_OK;
785         }
786         
787         if (argc > 1)
788                 sscanf(argv[1], "%x", &access_mask);
789
790         if (argc > 2)
791                 sscanf(argv[2], "%hx", &acb_mask);
792
793         /* Get sam policy handle */
794
795         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
796                                    &connect_pol);
797
798         if (!NT_STATUS_IS_OK(result))
799                 goto done;
800
801         got_connect_pol = True;
802
803         /* Get domain policy handle */
804
805         result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
806                                       access_mask,
807                                       &domain_sid, &domain_pol);
808
809         if (!NT_STATUS_IS_OK(result))
810                 goto done;
811
812         got_domain_pol = True;
813
814         /* Enumerate domain users */
815
816         start_idx = 0;
817         size = 0xffff;
818
819         do {
820                 result = rpccli_samr_enum_dom_users(
821                         cli, mem_ctx, &domain_pol, &start_idx, acb_mask,
822                         size, &dom_users, &dom_rids, &num_dom_users);
823
824                 if (NT_STATUS_IS_OK(result) ||
825                     NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES)) {
826
827                         for (i = 0; i < num_dom_users; i++)
828                                printf("user:[%s] rid:[0x%x]\n", 
829                                        dom_users[i], dom_rids[i]);
830                 }
831
832         } while (NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES));
833
834  done:
835         if (got_domain_pol)
836                 rpccli_samr_close(cli, mem_ctx, &domain_pol);
837
838         if (got_connect_pol)
839                 rpccli_samr_close(cli, mem_ctx, &connect_pol);
840
841         return result;
842 }
843
844 /* Enumerate domain groups */
845
846 static NTSTATUS cmd_samr_enum_dom_groups(struct rpc_pipe_client *cli, 
847                                          TALLOC_CTX *mem_ctx,
848                                          int argc, const char **argv) 
849 {
850         POLICY_HND connect_pol, domain_pol;
851         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
852         uint32 start_idx, size, num_dom_groups, i;
853         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
854         struct acct_info *dom_groups;
855         BOOL got_connect_pol = False, got_domain_pol = False;
856
857         if ((argc < 1) || (argc > 2)) {
858                 printf("Usage: %s [access_mask]\n", argv[0]);
859                 return NT_STATUS_OK;
860         }
861         
862         if (argc > 1)
863                 sscanf(argv[1], "%x", &access_mask);
864
865         /* Get sam policy handle */
866
867         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
868                                    &connect_pol);
869
870         if (!NT_STATUS_IS_OK(result))
871                 goto done;
872
873         got_connect_pol = True;
874
875         /* Get domain policy handle */
876
877         result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
878                                       access_mask,
879                                       &domain_sid, &domain_pol);
880
881         if (!NT_STATUS_IS_OK(result))
882                 goto done;
883
884         got_domain_pol = True;
885
886         /* Enumerate domain groups */
887
888         start_idx = 0;
889         size = 0xffff;
890
891         do {
892                 result = rpccli_samr_enum_dom_groups(
893                         cli, mem_ctx, &domain_pol, &start_idx, size,
894                         &dom_groups, &num_dom_groups);
895
896                 if (NT_STATUS_IS_OK(result) ||
897                     NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES)) {
898
899                         for (i = 0; i < num_dom_groups; i++)
900                                 printf("group:[%s] rid:[0x%x]\n", 
901                                        dom_groups[i].acct_name,
902                                        dom_groups[i].rid);
903                 }
904
905         } while (NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES));
906
907  done:
908         if (got_domain_pol)
909                 rpccli_samr_close(cli, mem_ctx, &domain_pol);
910
911         if (got_connect_pol)
912                 rpccli_samr_close(cli, mem_ctx, &connect_pol);
913
914         return result;
915 }
916
917 /* Enumerate alias groups */
918
919 static NTSTATUS cmd_samr_enum_als_groups(struct rpc_pipe_client *cli, 
920                                          TALLOC_CTX *mem_ctx,
921                                          int argc, const char **argv) 
922 {
923         POLICY_HND connect_pol, domain_pol;
924         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
925         uint32 start_idx, size, num_als_groups, i;
926         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
927         struct acct_info *als_groups;
928         BOOL got_connect_pol = False, got_domain_pol = False;
929
930         if ((argc < 2) || (argc > 3)) {
931                 printf("Usage: %s builtin|domain [access mask]\n", argv[0]);
932                 return NT_STATUS_OK;
933         }
934         
935         if (argc > 2)
936                 sscanf(argv[2], "%x", &access_mask);
937
938         /* Get sam policy handle */
939
940         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
941                                    &connect_pol);
942
943         if (!NT_STATUS_IS_OK(result))
944                 goto done;
945
946         got_connect_pol = True;
947
948         /* Get domain policy handle */
949
950         if (StrCaseCmp(argv[1], "domain")==0)
951                 result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
952                                               access_mask,
953                                               &domain_sid, &domain_pol);
954         else if (StrCaseCmp(argv[1], "builtin")==0)
955                 result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
956                                               access_mask,
957                                               &global_sid_Builtin, &domain_pol);
958         else
959                 return NT_STATUS_OK;
960
961         if (!NT_STATUS_IS_OK(result))
962                 goto done;
963
964         got_domain_pol = True;
965
966         /* Enumerate alias groups */
967
968         start_idx = 0;
969         size = 0xffff;          /* Number of groups to retrieve */
970
971         do {
972                 result = rpccli_samr_enum_als_groups(
973                         cli, mem_ctx, &domain_pol, &start_idx, size,
974                         &als_groups, &num_als_groups);
975
976                 if (NT_STATUS_IS_OK(result) ||
977                     NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES)) {
978
979                         for (i = 0; i < num_als_groups; i++)
980                                 printf("group:[%s] rid:[0x%x]\n", 
981                                        als_groups[i].acct_name,
982                                        als_groups[i].rid);
983                 }
984         } while (NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES));
985
986  done:
987         if (got_domain_pol)
988                 rpccli_samr_close(cli, mem_ctx, &domain_pol);
989         
990         if (got_connect_pol)
991                 rpccli_samr_close(cli, mem_ctx, &connect_pol);
992         
993         return result;
994 }
995
996 /* Query alias membership */
997
998 static NTSTATUS cmd_samr_query_aliasmem(struct rpc_pipe_client *cli, 
999                                         TALLOC_CTX *mem_ctx,
1000                                         int argc, const char **argv) 
1001 {
1002         POLICY_HND connect_pol, domain_pol, alias_pol;
1003         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1004         uint32 alias_rid, num_members, i;
1005         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1006         DOM_SID *alias_sids;
1007
1008         if ((argc < 3) || (argc > 4)) {
1009                 printf("Usage: %s builtin|domain rid [access mask]\n", argv[0]);
1010                 return NT_STATUS_OK;
1011         }
1012
1013         sscanf(argv[2], "%i", &alias_rid);
1014         
1015         if (argc > 3)
1016                 sscanf(argv[3], "%x", &access_mask);
1017
1018         /* Open SAMR handle */
1019
1020         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1021                                    &connect_pol);
1022
1023         if (!NT_STATUS_IS_OK(result))
1024                 goto done;
1025
1026         /* Open handle on domain */
1027         
1028         if (StrCaseCmp(argv[1], "domain")==0)
1029                 result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
1030                                               MAXIMUM_ALLOWED_ACCESS,
1031                                               &domain_sid, &domain_pol);
1032         else if (StrCaseCmp(argv[1], "builtin")==0)
1033                 result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
1034                                               MAXIMUM_ALLOWED_ACCESS,
1035                                               &global_sid_Builtin, &domain_pol);
1036         else
1037                 return NT_STATUS_OK;
1038
1039         if (!NT_STATUS_IS_OK(result))
1040                 goto done;
1041
1042         /* Open handle on alias */
1043
1044         result = rpccli_samr_open_alias(cli, mem_ctx, &domain_pol,
1045                                      access_mask,
1046                                      alias_rid, &alias_pol);
1047         if (!NT_STATUS_IS_OK(result))
1048                 goto done;
1049
1050         result = rpccli_samr_query_aliasmem(cli, mem_ctx, &alias_pol,
1051                                          &num_members, &alias_sids);
1052
1053         if (!NT_STATUS_IS_OK(result))
1054                 goto done;
1055
1056         for (i = 0; i < num_members; i++) {
1057                 fstring sid_str;
1058
1059                 sid_to_string(sid_str, &alias_sids[i]);
1060                 printf("\tsid:[%s]\n", sid_str);
1061         }
1062
1063         rpccli_samr_close(cli, mem_ctx, &alias_pol);
1064         rpccli_samr_close(cli, mem_ctx, &domain_pol);
1065         rpccli_samr_close(cli, mem_ctx, &connect_pol);
1066  done:
1067         return result;
1068 }
1069
1070 /* Query delete an alias membership */
1071
1072 static NTSTATUS cmd_samr_delete_alias(struct rpc_pipe_client *cli, 
1073                                       TALLOC_CTX *mem_ctx,
1074                                       int argc, const char **argv) 
1075 {
1076         POLICY_HND connect_pol, domain_pol, alias_pol;
1077         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1078         uint32 alias_rid;
1079         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1080
1081         if (argc != 3) {
1082                 printf("Usage: %s builtin|domain [rid|name]\n", argv[0]);
1083                 return NT_STATUS_OK;
1084         }
1085
1086         alias_rid = strtoul(argv[2], NULL, 10);
1087         
1088         /* Open SAMR handle */
1089
1090         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1091                                    &connect_pol);
1092
1093         if (!NT_STATUS_IS_OK(result))
1094                 goto done;
1095
1096         /* Open handle on domain */
1097         
1098         if (StrCaseCmp(argv[1], "domain")==0)
1099                 result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
1100                                               MAXIMUM_ALLOWED_ACCESS,
1101                                               &domain_sid, &domain_pol);
1102         else if (StrCaseCmp(argv[1], "builtin")==0)
1103                 result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
1104                                               MAXIMUM_ALLOWED_ACCESS,
1105                                               &global_sid_Builtin, &domain_pol);
1106         else
1107                 return NT_STATUS_INVALID_PARAMETER;
1108
1109         if (!NT_STATUS_IS_OK(result))
1110                 goto done;
1111
1112         /* Open handle on alias */
1113
1114         result = rpccli_samr_open_alias(cli, mem_ctx, &domain_pol,
1115                                      access_mask,
1116                                      alias_rid, &alias_pol);
1117         if (!NT_STATUS_IS_OK(result) && (alias_rid == 0)) {
1118                 /* Probably this was a user name, try lookupnames */
1119                 uint32 num_rids;
1120                 uint32 *rids, *types;
1121                 
1122                 result = rpccli_samr_lookup_names(cli, mem_ctx, &domain_pol,
1123                                                   1000, 1, &argv[2],
1124                                                   &num_rids, &rids,
1125                                                   &types);
1126
1127                 if (NT_STATUS_IS_OK(result)) {
1128                         result = rpccli_samr_open_alias(cli, mem_ctx,
1129                                                        &domain_pol,
1130                                                        access_mask,
1131                                                        rids[0], &alias_pol);
1132                 }
1133         }
1134
1135         result = rpccli_samr_delete_dom_alias(cli, mem_ctx, &alias_pol);
1136
1137         if (!NT_STATUS_IS_OK(result))
1138                 goto done;
1139
1140         rpccli_samr_close(cli, mem_ctx, &domain_pol);
1141         rpccli_samr_close(cli, mem_ctx, &connect_pol);
1142  done:
1143         return result;
1144 }
1145
1146 /* Query display info */
1147
1148 static NTSTATUS cmd_samr_query_dispinfo(struct rpc_pipe_client *cli, 
1149                                         TALLOC_CTX *mem_ctx,
1150                                         int argc, const char **argv) 
1151 {
1152         POLICY_HND connect_pol, domain_pol;
1153         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1154         uint32 start_idx=0, max_entries=250, max_size = 0xffff, num_entries, i;
1155         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1156         uint32 info_level = 1;
1157         SAM_DISPINFO_CTR ctr;
1158         SAM_DISPINFO_1 info1;
1159         SAM_DISPINFO_2 info2;
1160         SAM_DISPINFO_3 info3;
1161         SAM_DISPINFO_4 info4;
1162         SAM_DISPINFO_5 info5;
1163         int loop_count = 0;
1164         BOOL got_params = False; /* Use get_query_dispinfo_params() or not? */
1165
1166         if (argc > 5) {
1167                 printf("Usage: %s [info level] [start index] [max entries] [max size] [access mask]\n", argv[0]);
1168                 return NT_STATUS_OK;
1169         }
1170
1171         if (argc >= 2)
1172                 sscanf(argv[1], "%i", &info_level);
1173         
1174         if (argc >= 3)
1175                 sscanf(argv[2], "%i", &start_idx);
1176         
1177         if (argc >= 4) {
1178                 sscanf(argv[3], "%i", &max_entries);
1179                 got_params = True;
1180         }
1181         
1182         if (argc >= 5) {
1183                 sscanf(argv[4], "%i", &max_size);
1184                 got_params = True;
1185         }
1186         
1187         if (argc >= 6)
1188                 sscanf(argv[5], "%x", &access_mask);
1189
1190         /* Get sam policy handle */
1191
1192         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1193                                    &connect_pol);
1194
1195         if (!NT_STATUS_IS_OK(result))
1196                 goto done;
1197
1198         /* Get domain policy handle */
1199
1200         result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
1201                                       access_mask, 
1202                                       &domain_sid, &domain_pol);
1203
1204         if (!NT_STATUS_IS_OK(result))
1205                 goto done;
1206
1207         /* Query display info */
1208
1209         ZERO_STRUCT(ctr);
1210         ZERO_STRUCT(info1);
1211         
1212         switch (info_level) {
1213         case 1:
1214                 ZERO_STRUCT(info1);
1215                 ctr.sam.info1 = &info1;
1216                 break;
1217         case 2:
1218                 ZERO_STRUCT(info2);
1219                 ctr.sam.info2 = &info2;
1220                 break;
1221         case 3:
1222                 ZERO_STRUCT(info3);
1223                 ctr.sam.info3 = &info3;
1224                 break;
1225         case 4:
1226                 ZERO_STRUCT(info4);
1227                 ctr.sam.info4 = &info4;
1228                 break;
1229         case 5:
1230                 ZERO_STRUCT(info5);
1231                 ctr.sam.info5 = &info5;
1232                 break;
1233         }
1234
1235
1236         do {
1237
1238                 if (!got_params)
1239                         get_query_dispinfo_params(
1240                                 loop_count, &max_entries, &max_size);
1241                 
1242                 result = rpccli_samr_query_dispinfo(cli, mem_ctx, &domain_pol,
1243                                                  &start_idx, info_level,
1244                                                  &num_entries, max_entries, 
1245                                                  max_size, &ctr);
1246
1247                 loop_count++;
1248
1249                 if (NT_STATUS_IS_ERR(result))
1250                         break;
1251
1252                 if (num_entries == 0) 
1253                         break;
1254
1255                 for (i = 0; i < num_entries; i++) {
1256                         switch (info_level) {
1257                         case 1:
1258                                 display_sam_info_1(&ctr.sam.info1->sam[i], &ctr.sam.info1->str[i]);
1259                                 break;
1260                         case 2:
1261                                 display_sam_info_2(&ctr.sam.info2->sam[i], &ctr.sam.info2->str[i]);
1262                                 break;
1263                         case 3:
1264                                 display_sam_info_3(&ctr.sam.info3->sam[i], &ctr.sam.info3->str[i]);
1265                                 break;
1266                         case 4:
1267                                 display_sam_info_4(&ctr.sam.info4->sam[i], &ctr.sam.info4->str[i]);
1268                                 break;
1269                         case 5:
1270                                 display_sam_info_5(&ctr.sam.info5->sam[i], &ctr.sam.info5->str[i]);
1271                                 break;
1272                         }
1273                 }
1274         } while ( NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
1275
1276         rpccli_samr_close(cli, mem_ctx, &domain_pol);
1277         rpccli_samr_close(cli, mem_ctx, &connect_pol);
1278  done:
1279         return result;
1280 }
1281
1282 /* Query domain info */
1283
1284 static NTSTATUS cmd_samr_query_dominfo(struct rpc_pipe_client *cli, 
1285                                        TALLOC_CTX *mem_ctx,
1286                                        int argc, const char **argv) 
1287 {
1288         POLICY_HND connect_pol, domain_pol;
1289         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1290         uint32 switch_level = 2;
1291         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1292         SAM_UNK_CTR ctr;
1293
1294         if (argc > 2) {
1295                 printf("Usage: %s [info level] [access mask]\n", argv[0]);
1296                 return NT_STATUS_OK;
1297         }
1298
1299         if (argc > 1)
1300                 sscanf(argv[1], "%i", &switch_level);
1301         
1302         if (argc > 2)
1303                 sscanf(argv[2], "%x", &access_mask);
1304
1305         /* Get sam policy handle */
1306
1307         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1308                                    &connect_pol);
1309
1310         if (!NT_STATUS_IS_OK(result))
1311                 goto done;
1312
1313         /* Get domain policy handle */
1314
1315         result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
1316                                       access_mask,
1317                                       &domain_sid, &domain_pol);
1318
1319         if (!NT_STATUS_IS_OK(result))
1320                 goto done;
1321
1322         /* Query domain info */
1323
1324         result = rpccli_samr_query_dom_info(cli, mem_ctx, &domain_pol,
1325                                          switch_level, &ctr);
1326
1327         if (!NT_STATUS_IS_OK(result))
1328                 goto done;
1329
1330         /* Display domain info */
1331
1332         switch (switch_level) {
1333         case 1:
1334                 display_sam_unk_info_1(&ctr.info.inf1);
1335                 break;
1336         case 2:
1337                 display_sam_unk_info_2(&ctr.info.inf2);
1338                 break;
1339         case 7:
1340                 display_sam_unk_info_7(&ctr.info.inf7);
1341                 break;
1342         case 8:
1343                 display_sam_unk_info_8(&ctr.info.inf8);
1344                 break;
1345         case 12:
1346                 display_sam_unk_info_12(&ctr.info.inf12);
1347                 break;
1348         default:
1349                 printf("cannot display domain info for switch value %d\n",
1350                        switch_level);
1351                 break;
1352         }
1353
1354  done:
1355  
1356         rpccli_samr_close(cli, mem_ctx, &domain_pol);
1357         rpccli_samr_close(cli, mem_ctx, &connect_pol);
1358         return result;
1359 }
1360
1361 /* Create domain user */
1362
1363 static NTSTATUS cmd_samr_create_dom_user(struct rpc_pipe_client *cli, 
1364                                          TALLOC_CTX *mem_ctx,
1365                                          int argc, const char **argv) 
1366 {
1367         POLICY_HND connect_pol, domain_pol, user_pol;
1368         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1369         const char *acct_name;
1370         uint16 acb_info;
1371         uint32 unknown, user_rid;
1372         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1373
1374         if ((argc < 2) || (argc > 3)) {
1375                 printf("Usage: %s username [access mask]\n", argv[0]);
1376                 return NT_STATUS_OK;
1377         }
1378
1379         acct_name = argv[1];
1380         
1381         if (argc > 2)
1382                 sscanf(argv[2], "%x", &access_mask);
1383
1384         /* Get sam policy handle */
1385
1386         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1387                                    &connect_pol);
1388
1389         if (!NT_STATUS_IS_OK(result))
1390                 goto done;
1391
1392         /* Get domain policy handle */
1393
1394         result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
1395                                       access_mask,
1396                                       &domain_sid, &domain_pol);
1397
1398         if (!NT_STATUS_IS_OK(result))
1399                 goto done;
1400
1401         /* Create domain user */
1402
1403         acb_info = ACB_NORMAL;
1404         unknown = 0xe005000b; /* No idea what this is - a permission mask? */
1405
1406         result = rpccli_samr_create_dom_user(cli, mem_ctx, &domain_pol,
1407                                           acct_name, acb_info, unknown,
1408                                           &user_pol, &user_rid);
1409
1410         if (!NT_STATUS_IS_OK(result))
1411                 goto done;
1412
1413         result = rpccli_samr_close(cli, mem_ctx, &user_pol);
1414         if (!NT_STATUS_IS_OK(result)) goto done;
1415
1416         result = rpccli_samr_close(cli, mem_ctx, &domain_pol);
1417         if (!NT_STATUS_IS_OK(result)) goto done;
1418
1419         result = rpccli_samr_close(cli, mem_ctx, &connect_pol);
1420         if (!NT_STATUS_IS_OK(result)) goto done;
1421
1422  done:
1423         return result;
1424 }
1425
1426 /* Create domain group */
1427
1428 static NTSTATUS cmd_samr_create_dom_group(struct rpc_pipe_client *cli, 
1429                                           TALLOC_CTX *mem_ctx,
1430                                           int argc, const char **argv) 
1431 {
1432         POLICY_HND connect_pol, domain_pol, group_pol;
1433         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1434         const char *grp_name;
1435         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1436
1437         if ((argc < 2) || (argc > 3)) {
1438                 printf("Usage: %s groupname [access mask]\n", argv[0]);
1439                 return NT_STATUS_OK;
1440         }
1441
1442         grp_name = argv[1];
1443         
1444         if (argc > 2)
1445                 sscanf(argv[2], "%x", &access_mask);
1446
1447         /* Get sam policy handle */
1448
1449         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1450                                    &connect_pol);
1451
1452         if (!NT_STATUS_IS_OK(result))
1453                 goto done;
1454
1455         /* Get domain policy handle */
1456
1457         result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
1458                                       access_mask,
1459                                       &domain_sid, &domain_pol);
1460
1461         if (!NT_STATUS_IS_OK(result))
1462                 goto done;
1463
1464         /* Create domain user */
1465
1466         result = rpccli_samr_create_dom_group(cli, mem_ctx, &domain_pol,
1467                                            grp_name, MAXIMUM_ALLOWED_ACCESS,
1468                                            &group_pol);
1469
1470         if (!NT_STATUS_IS_OK(result))
1471                 goto done;
1472
1473         result = rpccli_samr_close(cli, mem_ctx, &group_pol);
1474         if (!NT_STATUS_IS_OK(result)) goto done;
1475
1476         result = rpccli_samr_close(cli, mem_ctx, &domain_pol);
1477         if (!NT_STATUS_IS_OK(result)) goto done;
1478
1479         result = rpccli_samr_close(cli, mem_ctx, &connect_pol);
1480         if (!NT_STATUS_IS_OK(result)) goto done;
1481
1482  done:
1483         return result;
1484 }
1485
1486 /* Create domain alias */
1487
1488 static NTSTATUS cmd_samr_create_dom_alias(struct rpc_pipe_client *cli, 
1489                                           TALLOC_CTX *mem_ctx,
1490                                           int argc, const char **argv) 
1491 {
1492         POLICY_HND connect_pol, domain_pol, alias_pol;
1493         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1494         const char *alias_name;
1495         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1496
1497         if ((argc < 2) || (argc > 3)) {
1498                 printf("Usage: %s aliasname [access mask]\n", argv[0]);
1499                 return NT_STATUS_OK;
1500         }
1501
1502         alias_name = argv[1];
1503         
1504         if (argc > 2)
1505                 sscanf(argv[2], "%x", &access_mask);
1506
1507         /* Get sam policy handle */
1508
1509         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1510                                    &connect_pol);
1511
1512         if (!NT_STATUS_IS_OK(result))
1513                 goto done;
1514
1515         /* Get domain policy handle */
1516
1517         result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
1518                                          access_mask,
1519                                          &domain_sid, &domain_pol);
1520
1521         if (!NT_STATUS_IS_OK(result))
1522                 goto done;
1523
1524         /* Create domain user */
1525
1526         result = rpccli_samr_create_dom_alias(cli, mem_ctx, &domain_pol,
1527                                               alias_name, &alias_pol);
1528
1529         if (!NT_STATUS_IS_OK(result))
1530                 goto done;
1531
1532         result = rpccli_samr_close(cli, mem_ctx, &alias_pol);
1533         if (!NT_STATUS_IS_OK(result)) goto done;
1534
1535         result = rpccli_samr_close(cli, mem_ctx, &domain_pol);
1536         if (!NT_STATUS_IS_OK(result)) goto done;
1537
1538         result = rpccli_samr_close(cli, mem_ctx, &connect_pol);
1539         if (!NT_STATUS_IS_OK(result)) goto done;
1540
1541  done:
1542         return result;
1543 }
1544
1545 /* Lookup sam names */
1546
1547 static NTSTATUS cmd_samr_lookup_names(struct rpc_pipe_client *cli, 
1548                                       TALLOC_CTX *mem_ctx,
1549                                       int argc, const char **argv) 
1550 {
1551         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1552         POLICY_HND connect_pol, domain_pol;
1553         uint32 flags = 0x000003e8; /* Unknown */
1554         uint32 num_rids, num_names, *name_types, *rids;
1555         const char **names;
1556         int i;
1557
1558         if (argc < 3) {
1559                 printf("Usage: %s  domain|builtin name1 [name2 [name3] [...]]\n", argv[0]);
1560                 printf("check on the domain SID: S-1-5-21-x-y-z\n");
1561                 printf("or check on the builtin SID: S-1-5-32\n");
1562                 return NT_STATUS_OK;
1563         }
1564
1565         /* Get sam policy and domain handles */
1566
1567         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1568                                    &connect_pol);
1569
1570         if (!NT_STATUS_IS_OK(result))
1571                 goto done;
1572
1573         if (StrCaseCmp(argv[1], "domain")==0)
1574                 result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
1575                                               MAXIMUM_ALLOWED_ACCESS,
1576                                               &domain_sid, &domain_pol);
1577         else if (StrCaseCmp(argv[1], "builtin")==0)
1578                 result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
1579                                               MAXIMUM_ALLOWED_ACCESS,
1580                                               &global_sid_Builtin, &domain_pol);
1581         else
1582                 return NT_STATUS_OK;
1583
1584         if (!NT_STATUS_IS_OK(result))
1585                 goto done;
1586
1587         /* Look up names */
1588
1589         num_names = argc - 2;
1590         names = TALLOC_ARRAY(mem_ctx, const char *, num_names);
1591
1592         for (i = 0; i < argc - 2; i++)
1593                 names[i] = argv[i + 2];
1594
1595         result = rpccli_samr_lookup_names(cli, mem_ctx, &domain_pol,
1596                                        flags, num_names, names,
1597                                        &num_rids, &rids, &name_types);
1598
1599         if (!NT_STATUS_IS_OK(result))
1600                 goto done;
1601
1602         /* Display results */
1603
1604         for (i = 0; i < num_names; i++)
1605                 printf("name %s: 0x%x (%d)\n", names[i], rids[i], 
1606                        name_types[i]);
1607
1608         rpccli_samr_close(cli, mem_ctx, &domain_pol);
1609         rpccli_samr_close(cli, mem_ctx, &connect_pol);
1610  done:
1611         return result;
1612 }
1613
1614 /* Lookup sam rids */
1615
1616 static NTSTATUS cmd_samr_lookup_rids(struct rpc_pipe_client *cli, 
1617                                      TALLOC_CTX *mem_ctx,
1618                                      int argc, const char **argv) 
1619 {
1620         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1621         POLICY_HND connect_pol, domain_pol;
1622         uint32 num_rids, num_names, *rids, *name_types;
1623         char **names;
1624         int i;
1625
1626         if (argc < 3) {
1627                 printf("Usage: %s domain|builtin rid1 [rid2 [rid3] [...]]\n", argv[0]);
1628                 return NT_STATUS_OK;
1629         }
1630
1631         /* Get sam policy and domain handles */
1632
1633         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1634                                    &connect_pol);
1635
1636         if (!NT_STATUS_IS_OK(result))
1637                 goto done;
1638
1639         if (StrCaseCmp(argv[1], "domain")==0)
1640                 result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
1641                                               MAXIMUM_ALLOWED_ACCESS,
1642                                               &domain_sid, &domain_pol);
1643         else if (StrCaseCmp(argv[1], "builtin")==0)
1644                 result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
1645                                               MAXIMUM_ALLOWED_ACCESS,
1646                                               &global_sid_Builtin, &domain_pol);
1647         else
1648                 return NT_STATUS_OK;
1649
1650         if (!NT_STATUS_IS_OK(result))
1651                 goto done;
1652
1653         /* Look up rids */
1654
1655         num_rids = argc - 2;
1656         rids = TALLOC_ARRAY(mem_ctx, uint32, num_rids);
1657
1658         for (i = 0; i < argc - 2; i++)
1659                 sscanf(argv[i + 2], "%i", &rids[i]);
1660
1661         result = rpccli_samr_lookup_rids(cli, mem_ctx, &domain_pol, num_rids, rids,
1662                                       &num_names, &names, &name_types);
1663
1664         if (!NT_STATUS_IS_OK(result) &&
1665             !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED))
1666                 goto done;
1667
1668         /* Display results */
1669
1670         for (i = 0; i < num_names; i++)
1671                 printf("rid 0x%x: %s (%d)\n", rids[i], names[i], name_types[i]);
1672
1673         rpccli_samr_close(cli, mem_ctx, &domain_pol);
1674         rpccli_samr_close(cli, mem_ctx, &connect_pol);
1675  done:
1676         return result;
1677 }
1678
1679 /* Delete domain user */
1680
1681 static NTSTATUS cmd_samr_delete_dom_user(struct rpc_pipe_client *cli, 
1682                                          TALLOC_CTX *mem_ctx,
1683                                          int argc, const char **argv) 
1684 {
1685         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1686         POLICY_HND connect_pol, domain_pol, user_pol;
1687         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1688
1689         if ((argc < 2) || (argc > 3)) {
1690                 printf("Usage: %s username\n", argv[0]);
1691                 return NT_STATUS_OK;
1692         }
1693         
1694         if (argc > 2)
1695                 sscanf(argv[2], "%x", &access_mask);
1696
1697         /* Get sam policy and domain handles */
1698
1699         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1700                                    &connect_pol);
1701
1702         if (!NT_STATUS_IS_OK(result))
1703                 goto done;
1704
1705         result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
1706                                       MAXIMUM_ALLOWED_ACCESS,
1707                                       &domain_sid, &domain_pol);
1708
1709         if (!NT_STATUS_IS_OK(result))
1710                 goto done;
1711
1712         /* Get handle on user */
1713
1714         {
1715                 uint32 *user_rids, num_rids, *name_types;
1716                 uint32 flags = 0x000003e8; /* Unknown */
1717
1718                 result = rpccli_samr_lookup_names(cli, mem_ctx, &domain_pol,
1719                                                flags, 1, (const char **)&argv[1],
1720                                                &num_rids, &user_rids,
1721                                                &name_types);
1722
1723                 if (!NT_STATUS_IS_OK(result))
1724                         goto done;
1725
1726                 result = rpccli_samr_open_user(cli, mem_ctx, &domain_pol,
1727                                             access_mask,
1728                                             user_rids[0], &user_pol);
1729
1730                 if (!NT_STATUS_IS_OK(result))
1731                         goto done;
1732         }
1733
1734         /* Delete user */
1735
1736         result = rpccli_samr_delete_dom_user(cli, mem_ctx, &user_pol);
1737
1738         if (!NT_STATUS_IS_OK(result))
1739                 goto done;
1740
1741         /* Display results */
1742
1743         rpccli_samr_close(cli, mem_ctx, &user_pol);
1744         rpccli_samr_close(cli, mem_ctx, &domain_pol);
1745         rpccli_samr_close(cli, mem_ctx, &connect_pol);
1746
1747  done:
1748         return result;
1749 }
1750
1751 /**********************************************************************
1752  * Query user security object 
1753  */
1754 static NTSTATUS cmd_samr_query_sec_obj(struct rpc_pipe_client *cli, 
1755                                     TALLOC_CTX *mem_ctx,
1756                                     int argc, const char **argv) 
1757 {
1758         POLICY_HND connect_pol, domain_pol, user_pol, *pol;
1759         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1760         uint32 info_level = 4;
1761         fstring server;
1762         uint32 user_rid = 0;
1763         TALLOC_CTX *ctx = NULL;
1764         SEC_DESC_BUF *sec_desc_buf=NULL;
1765         BOOL domain = False;
1766
1767         ctx=talloc_init("cmd_samr_query_sec_obj");
1768         
1769         if ((argc < 1) || (argc > 2)) {
1770                 printf("Usage: %s [rid|-d]\n", argv[0]);
1771                 printf("\tSpecify rid for security on user, -d for security on domain\n");
1772                 return NT_STATUS_OK;
1773         }
1774         
1775         if (argc > 1) {
1776                 if (strcmp(argv[1], "-d") == 0)
1777                         domain = True;
1778                 else
1779                         sscanf(argv[1], "%i", &user_rid);
1780         }
1781         
1782         slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost);
1783         strupper_m(server);
1784         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
1785                                    &connect_pol);
1786
1787         if (!NT_STATUS_IS_OK(result))
1788                 goto done;
1789
1790         if (domain || user_rid)
1791                 result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
1792                                               MAXIMUM_ALLOWED_ACCESS,
1793                                               &domain_sid, &domain_pol);
1794
1795         if (!NT_STATUS_IS_OK(result))
1796                 goto done;
1797
1798         if (user_rid)
1799                 result = rpccli_samr_open_user(cli, mem_ctx, &domain_pol,
1800                                             MAXIMUM_ALLOWED_ACCESS,
1801                                             user_rid, &user_pol);
1802
1803         if (!NT_STATUS_IS_OK(result))
1804                 goto done;
1805
1806         /* Pick which query pol to use */
1807
1808         pol = &connect_pol;
1809
1810         if (domain)
1811                 pol = &domain_pol;
1812
1813         if (user_rid)
1814                 pol = &user_pol;
1815
1816         /* Query SAM security object */
1817
1818         result = rpccli_samr_query_sec_obj(cli, mem_ctx, pol, info_level, ctx, 
1819                                         &sec_desc_buf);
1820
1821         if (!NT_STATUS_IS_OK(result))
1822                 goto done;
1823
1824         display_sec_desc(sec_desc_buf->sec);
1825         
1826         rpccli_samr_close(cli, mem_ctx, &user_pol);
1827         rpccli_samr_close(cli, mem_ctx, &domain_pol);
1828         rpccli_samr_close(cli, mem_ctx, &connect_pol);
1829 done:
1830         talloc_destroy(ctx);
1831         return result;
1832 }
1833
1834 static NTSTATUS cmd_samr_get_usrdom_pwinfo(struct rpc_pipe_client *cli, 
1835                                            TALLOC_CTX *mem_ctx,
1836                                            int argc, const char **argv) 
1837 {
1838         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1839         POLICY_HND connect_pol, domain_pol, user_pol;
1840         uint16 min_pwd_length;
1841         uint32 password_properties, unknown1, rid;
1842
1843         if (argc != 2) {
1844                 printf("Usage: %s rid\n", argv[0]);
1845                 return NT_STATUS_OK;
1846         }
1847         
1848         sscanf(argv[1], "%i", &rid);
1849
1850         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1851                                    &connect_pol);
1852
1853         if (!NT_STATUS_IS_OK(result)) {
1854                 goto done;
1855         }
1856
1857         result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
1858                                          MAXIMUM_ALLOWED_ACCESS, &domain_sid, &domain_pol);
1859
1860         if (!NT_STATUS_IS_OK(result)) {
1861                 goto done;
1862         }
1863
1864         result = rpccli_samr_open_user(cli, mem_ctx, &domain_pol,
1865                                        MAXIMUM_ALLOWED_ACCESS,
1866                                        rid, &user_pol);
1867
1868         if (!NT_STATUS_IS_OK(result)) {
1869                 goto done;
1870         }
1871
1872         result = rpccli_samr_get_usrdom_pwinfo(cli, mem_ctx, &user_pol,
1873                                                &min_pwd_length, &password_properties, 
1874                                                &unknown1) ;
1875
1876         if (NT_STATUS_IS_OK(result)) {
1877                 printf("min_pwd_length: %d\n", min_pwd_length);
1878                 printf("unknown1: %d\n", unknown1);
1879                 display_password_properties(password_properties);
1880         }
1881
1882  done:
1883         rpccli_samr_close(cli, mem_ctx, &user_pol);
1884         rpccli_samr_close(cli, mem_ctx, &domain_pol);
1885         rpccli_samr_close(cli, mem_ctx, &connect_pol);
1886
1887         return result;
1888 }
1889
1890
1891 static NTSTATUS cmd_samr_get_dom_pwinfo(struct rpc_pipe_client *cli, 
1892                                         TALLOC_CTX *mem_ctx,
1893                                         int argc, const char **argv) 
1894 {
1895         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1896         uint16 min_pwd_length;
1897         uint32 password_properties;
1898
1899         if (argc != 1) {
1900                 printf("Usage: %s\n", argv[0]);
1901                 return NT_STATUS_OK;
1902         }
1903
1904         result = rpccli_samr_get_dom_pwinfo(cli, mem_ctx, &min_pwd_length, &password_properties) ;
1905         
1906         if (NT_STATUS_IS_OK(result)) {
1907                 printf("min_pwd_length: %d\n", min_pwd_length);
1908                 display_password_properties(password_properties);
1909         }
1910
1911         return result;
1912 }
1913
1914 /* Look up domain name */
1915
1916 static NTSTATUS cmd_samr_lookup_domain(struct rpc_pipe_client *cli, 
1917                                        TALLOC_CTX *mem_ctx,
1918                                        int argc, const char **argv) 
1919 {
1920         POLICY_HND connect_pol, domain_pol;
1921         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1922         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1923         fstring domain_name,sid_string;
1924         DOM_SID sid;
1925         
1926         if (argc != 2) {
1927                 printf("Usage: %s domain_name\n", argv[0]);
1928                 return NT_STATUS_OK;
1929         }
1930         
1931         sscanf(argv[1], "%s", domain_name);
1932         
1933         result = try_samr_connects(cli, mem_ctx, access_mask, &connect_pol);
1934         
1935         if (!NT_STATUS_IS_OK(result))
1936                 goto done;
1937
1938         result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
1939                                       access_mask, &domain_sid, &domain_pol);
1940
1941         if (!NT_STATUS_IS_OK(result))
1942                 goto done;
1943         
1944         result = rpccli_samr_lookup_domain(
1945                 cli, mem_ctx, &connect_pol, domain_name, &sid);
1946
1947         sid_to_string(sid_string,&sid);
1948  
1949         if (NT_STATUS_IS_OK(result)) 
1950                 printf("SAMR_LOOKUP_DOMAIN: Domain Name: %s Domain SID: %s\n",
1951                        domain_name,sid_string);
1952
1953         rpccli_samr_close(cli, mem_ctx, &domain_pol);
1954         rpccli_samr_close(cli, mem_ctx, &connect_pol);
1955 done:
1956         return result;
1957 }
1958
1959 /* Change user password */
1960
1961 static NTSTATUS cmd_samr_chgpasswd3(struct rpc_pipe_client *cli, 
1962                                     TALLOC_CTX *mem_ctx,
1963                                     int argc, const char **argv) 
1964 {
1965         POLICY_HND connect_pol, domain_pol;
1966         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1967         const char *user, *oldpass, *newpass;
1968         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1969         SAM_UNK_INFO_1 info;
1970         SAMR_CHANGE_REJECT reject;
1971
1972         if (argc < 3) {
1973                 printf("Usage: %s username oldpass newpass\n", argv[0]);
1974                 return NT_STATUS_INVALID_PARAMETER;
1975         }
1976
1977         user = argv[1];
1978         oldpass = argv[2];
1979         newpass = argv[3];
1980         
1981         /* Get sam policy handle */
1982
1983         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1984                                    &connect_pol);
1985
1986         if (!NT_STATUS_IS_OK(result))
1987                 goto done;
1988
1989         /* Get domain policy handle */
1990
1991         result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
1992                                       access_mask,
1993                                       &domain_sid, &domain_pol);
1994
1995         if (!NT_STATUS_IS_OK(result))
1996                 goto done;
1997
1998         /* Change user password */
1999         result = rpccli_samr_chgpasswd3(cli, mem_ctx, user, newpass, oldpass, &info, &reject);
2000
2001         if (NT_STATUS_EQUAL(result, NT_STATUS_PASSWORD_RESTRICTION)) {
2002         
2003                 display_sam_unk_info_1(&info);
2004
2005                 switch (reject.reject_reason) {
2006                         case REJECT_REASON_TOO_SHORT:
2007                                 d_printf("REJECT_REASON_TOO_SHORT\n");
2008                                 break;
2009                         case REJECT_REASON_IN_HISTORY:
2010                                 d_printf("REJECT_REASON_IN_HISTORY\n");
2011                                 break;
2012                         case REJECT_REASON_NOT_COMPLEX:
2013                                 d_printf("REJECT_REASON_NOT_COMPLEX\n");
2014                                 break;
2015                         case 0:
2016                                 break;
2017                         default:
2018                                 d_printf("unknown reject reason: %d\n", reject.reject_reason);
2019                                 break;
2020                 }
2021         }
2022
2023         if (!NT_STATUS_IS_OK(result))
2024                 goto done;
2025
2026         result = rpccli_samr_close(cli, mem_ctx, &domain_pol);
2027         if (!NT_STATUS_IS_OK(result)) goto done;
2028
2029         result = rpccli_samr_close(cli, mem_ctx, &connect_pol);
2030         if (!NT_STATUS_IS_OK(result)) goto done;
2031
2032  done:
2033         return result;
2034 }
2035
2036 /* List of commands exported by this module */
2037
2038 struct cmd_set samr_commands[] = {
2039
2040         { "SAMR" },
2041
2042         { "queryuser",  RPC_RTYPE_NTSTATUS, cmd_samr_query_user,                NULL, PI_SAMR, NULL,    "Query user info",         "" },
2043         { "querygroup",         RPC_RTYPE_NTSTATUS, cmd_samr_query_group,               NULL, PI_SAMR, NULL,    "Query group info",        "" },
2044         { "queryusergroups",    RPC_RTYPE_NTSTATUS, cmd_samr_query_usergroups,  NULL, PI_SAMR, NULL,    "Query user groups",       "" },
2045         { "queryuseraliases",   RPC_RTYPE_NTSTATUS, cmd_samr_query_useraliases,         NULL, PI_SAMR, NULL,    "Query user aliases",      "" },
2046         { "querygroupmem",      RPC_RTYPE_NTSTATUS, cmd_samr_query_groupmem,    NULL, PI_SAMR, NULL,    "Query group membership",  "" },
2047         { "queryaliasmem",      RPC_RTYPE_NTSTATUS, cmd_samr_query_aliasmem,    NULL, PI_SAMR, NULL,    "Query alias membership",  "" },
2048         { "deletealias",        RPC_RTYPE_NTSTATUS, cmd_samr_delete_alias,      NULL, PI_SAMR, NULL,    "Delete an alias",  "" },
2049         { "querydispinfo",      RPC_RTYPE_NTSTATUS, cmd_samr_query_dispinfo,    NULL, PI_SAMR, NULL,    "Query display info",      "" },
2050         { "querydominfo",       RPC_RTYPE_NTSTATUS, cmd_samr_query_dominfo,     NULL, PI_SAMR, NULL,    "Query domain info",       "" },
2051         { "enumdomusers",      RPC_RTYPE_NTSTATUS, cmd_samr_enum_dom_users,       NULL, PI_SAMR, NULL,  "Enumerate domain users", "" },
2052         { "enumdomgroups",      RPC_RTYPE_NTSTATUS, cmd_samr_enum_dom_groups,       NULL, PI_SAMR, NULL,        "Enumerate domain groups", "" },
2053         { "enumalsgroups",      RPC_RTYPE_NTSTATUS, cmd_samr_enum_als_groups,       NULL, PI_SAMR, NULL,        "Enumerate alias groups",  "" },
2054
2055         { "createdomuser",      RPC_RTYPE_NTSTATUS, cmd_samr_create_dom_user,       NULL, PI_SAMR, NULL,        "Create domain user",      "" },
2056         { "createdomgroup",     RPC_RTYPE_NTSTATUS, cmd_samr_create_dom_group,      NULL, PI_SAMR, NULL,        "Create domain group",     "" },
2057         { "createdomalias",     RPC_RTYPE_NTSTATUS, cmd_samr_create_dom_alias,      NULL, PI_SAMR, NULL,        "Create domain alias",     "" },
2058         { "samlookupnames",     RPC_RTYPE_NTSTATUS, cmd_samr_lookup_names,          NULL, PI_SAMR, NULL,        "Look up names",           "" },
2059         { "samlookuprids",      RPC_RTYPE_NTSTATUS, cmd_samr_lookup_rids,           NULL, PI_SAMR, NULL,        "Look up names",           "" },
2060         { "deletedomuser",      RPC_RTYPE_NTSTATUS, cmd_samr_delete_dom_user,       NULL, PI_SAMR, NULL,        "Delete domain user",      "" },
2061         { "samquerysecobj",     RPC_RTYPE_NTSTATUS, cmd_samr_query_sec_obj,         NULL, PI_SAMR, NULL, "Query SAMR security object",   "" },
2062         { "getdompwinfo",       RPC_RTYPE_NTSTATUS, cmd_samr_get_dom_pwinfo,        NULL, PI_SAMR, NULL, "Retrieve domain password info", "" },
2063         { "getusrdompwinfo",    RPC_RTYPE_NTSTATUS, cmd_samr_get_usrdom_pwinfo,     NULL, PI_SAMR, NULL, "Retrieve user domain password info", "" },
2064
2065         { "lookupdomain",       RPC_RTYPE_NTSTATUS, cmd_samr_lookup_domain,         NULL, PI_SAMR, NULL, "Lookup Domain Name", "" },
2066         { "chgpasswd3",         RPC_RTYPE_NTSTATUS, cmd_samr_chgpasswd3,            NULL, PI_SAMR, NULL, "Change user password", "" },
2067         { NULL }
2068 };