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