r6117: Close handles after group-creation as well.
[kai/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_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 strdup("ROLE_STANDALONE");
149                         break;
150                 case ROLE_DOMAIN_MEMBER:
151                         return strdup("ROLE_DOMAIN_MEMBER");
152                         break;
153                 case ROLE_DOMAIN_BDC:
154                         return strdup("ROLE_DOMAIN_BDC");
155                         break;
156                 case ROLE_DOMAIN_PDC:
157                         return strdup("ROLE_DOMAIN_PDC");
158                         break;
159                 default:
160                         return 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         DOM_SID global_sid_Builtin;
579
580         string_to_sid(&global_sid_Builtin, "S-1-5-32");
581
582         if (argc < 3) {
583                 printf("Usage: %s builtin|domain sid1 sid2 ...\n", argv[0]);
584                 return NT_STATUS_INVALID_PARAMETER;
585         }
586
587         sids = NULL;
588         num_sids = 0;
589
590         for (i=2; i<argc; i++) {
591                 DOM_SID tmp_sid;
592                 if (!string_to_sid(&tmp_sid, argv[i])) {
593                         printf("%s is not a legal SID\n", argv[i]);
594                         return NT_STATUS_INVALID_PARAMETER;
595                 }
596                 add_sid_to_array(mem_ctx, &tmp_sid, &sids, &num_sids);
597         }
598
599         sid2 = TALLOC_ARRAY(mem_ctx, DOM_SID2, num_sids);
600         if (sid2 == NULL)
601                 return NT_STATUS_NO_MEMORY;
602
603         for (i=0; i<num_sids; i++) {
604                 sid_copy(&sid2[i].sid, &sids[i]);
605                 sid2[i].num_auths = sid2[i].sid.num_auths;
606         }
607
608         slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->desthost);
609         strupper_m(server);
610                 
611         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
612                                    &connect_pol);
613
614         if (!NT_STATUS_IS_OK(result))
615                 goto done;
616
617         if (StrCaseCmp(argv[1], "domain")==0)
618                 result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
619                                               access_mask,
620                                               &domain_sid, &domain_pol);
621         else if (StrCaseCmp(argv[1], "builtin")==0)
622                 result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
623                                               access_mask,
624                                               &global_sid_Builtin,
625                                               &domain_pol);
626         else {
627                 printf("Usage: %s builtin|domain sid1 sid2 ...\n", argv[0]);
628                 return NT_STATUS_INVALID_PARAMETER;
629         }
630
631         if (!NT_STATUS_IS_OK(result))
632                 goto done;
633
634         result = cli_samr_query_useraliases(cli, mem_ctx, &domain_pol,
635                                             num_sids, sid2,
636                                             &num_aliases, &alias_rids);
637
638         if (!NT_STATUS_IS_OK(result))
639                 goto done;
640
641         for (i = 0; i < num_aliases; i++) {
642                 printf("\tgroup rid:[0x%x]\n", alias_rids[i]);
643         }
644
645  done:
646         return result;
647 }
648
649 /* Query members of a group */
650
651 static NTSTATUS cmd_samr_query_groupmem(struct cli_state *cli, 
652                                         TALLOC_CTX *mem_ctx,
653                                         int argc, const char **argv) 
654 {
655         POLICY_HND connect_pol, domain_pol, group_pol;
656         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
657         uint32 num_members, *group_rids, *group_attrs, group_rid;
658         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
659         int i;
660         fstring                 server;
661         
662         if ((argc < 2) || (argc > 3)) {
663                 printf("Usage: %s rid [access mask]\n", argv[0]);
664                 return NT_STATUS_OK;
665         }
666
667         sscanf(argv[1], "%i", &group_rid);
668         
669         if (argc > 2)
670                 sscanf(argv[2], "%x", &access_mask);
671
672         slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->desthost);
673         strupper_m(server);
674
675         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
676                                    &connect_pol);
677
678         if (!NT_STATUS_IS_OK(result))
679                 goto done;
680
681         result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
682                                       MAXIMUM_ALLOWED_ACCESS,
683                                       &domain_sid, &domain_pol);
684
685         if (!NT_STATUS_IS_OK(result))
686                 goto done;
687
688         result = cli_samr_open_group(cli, mem_ctx, &domain_pol,
689                                      access_mask,
690                                      group_rid, &group_pol);
691
692         if (!NT_STATUS_IS_OK(result))
693                 goto done;
694
695         result = cli_samr_query_groupmem(cli, mem_ctx, &group_pol,
696                                          &num_members, &group_rids,
697                                          &group_attrs);
698
699         if (!NT_STATUS_IS_OK(result))
700                 goto done;
701
702         for (i = 0; i < num_members; i++) {
703                 printf("\trid:[0x%x] attr:[0x%x]\n", group_rids[i],
704                        group_attrs[i]);
705         }
706
707  done:
708         return result;
709 }
710
711 /* Enumerate domain users */
712
713 static NTSTATUS cmd_samr_enum_dom_users(struct cli_state *cli, 
714                                         TALLOC_CTX *mem_ctx,
715                                         int argc, const char **argv) 
716 {
717         POLICY_HND connect_pol, domain_pol;
718         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
719         uint32 start_idx, size, num_dom_users, i;
720         char **dom_users;
721         uint32 *dom_rids;
722         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
723         uint16 acb_mask = ACB_NORMAL;
724         BOOL got_connect_pol = False, got_domain_pol = False;
725
726         if ((argc < 1) || (argc > 3)) {
727                 printf("Usage: %s [access_mask] [acb_mask]\n", argv[0]);
728                 return NT_STATUS_OK;
729         }
730         
731         if (argc > 1)
732                 sscanf(argv[1], "%x", &access_mask);
733
734         if (argc > 2)
735                 sscanf(argv[2], "%hx", &acb_mask);
736
737         /* Get sam policy handle */
738
739         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
740                                    &connect_pol);
741
742         if (!NT_STATUS_IS_OK(result))
743                 goto done;
744
745         got_connect_pol = True;
746
747         /* Get domain policy handle */
748
749         result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
750                                       access_mask,
751                                       &domain_sid, &domain_pol);
752
753         if (!NT_STATUS_IS_OK(result))
754                 goto done;
755
756         got_domain_pol = True;
757
758         /* Enumerate domain users */
759
760         start_idx = 0;
761         size = 0xffff;
762
763         do {
764                 result = cli_samr_enum_dom_users(
765                         cli, mem_ctx, &domain_pol, &start_idx, acb_mask,
766                         size, &dom_users, &dom_rids, &num_dom_users);
767
768                 if (NT_STATUS_IS_OK(result) ||
769                     NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES)) {
770
771                         for (i = 0; i < num_dom_users; i++)
772                                printf("user:[%s] rid:[0x%x]\n", 
773                                        dom_users[i], dom_rids[i]);
774                 }
775
776         } while (NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES));
777
778  done:
779         if (got_domain_pol)
780                 cli_samr_close(cli, mem_ctx, &domain_pol);
781
782         if (got_connect_pol)
783                 cli_samr_close(cli, mem_ctx, &connect_pol);
784
785         return result;
786 }
787
788 /* Enumerate domain groups */
789
790 static NTSTATUS cmd_samr_enum_dom_groups(struct cli_state *cli, 
791                                          TALLOC_CTX *mem_ctx,
792                                          int argc, const char **argv) 
793 {
794         POLICY_HND connect_pol, domain_pol;
795         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
796         uint32 start_idx, size, num_dom_groups, i;
797         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
798         struct acct_info *dom_groups;
799         BOOL got_connect_pol = False, got_domain_pol = False;
800
801         if ((argc < 1) || (argc > 2)) {
802                 printf("Usage: %s [access_mask]\n", argv[0]);
803                 return NT_STATUS_OK;
804         }
805         
806         if (argc > 1)
807                 sscanf(argv[1], "%x", &access_mask);
808
809         /* Get sam policy handle */
810
811         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
812                                    &connect_pol);
813
814         if (!NT_STATUS_IS_OK(result))
815                 goto done;
816
817         got_connect_pol = True;
818
819         /* Get domain policy handle */
820
821         result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
822                                       access_mask,
823                                       &domain_sid, &domain_pol);
824
825         if (!NT_STATUS_IS_OK(result))
826                 goto done;
827
828         got_domain_pol = True;
829
830         /* Enumerate domain groups */
831
832         start_idx = 0;
833         size = 0xffff;
834
835         do {
836                 result = cli_samr_enum_dom_groups(
837                         cli, mem_ctx, &domain_pol, &start_idx, size,
838                         &dom_groups, &num_dom_groups);
839
840                 if (NT_STATUS_IS_OK(result) ||
841                     NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES)) {
842
843                         for (i = 0; i < num_dom_groups; i++)
844                                 printf("group:[%s] rid:[0x%x]\n", 
845                                        dom_groups[i].acct_name,
846                                        dom_groups[i].rid);
847                 }
848
849         } while (NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES));
850
851  done:
852         if (got_domain_pol)
853                 cli_samr_close(cli, mem_ctx, &domain_pol);
854
855         if (got_connect_pol)
856                 cli_samr_close(cli, mem_ctx, &connect_pol);
857
858         return result;
859 }
860
861 /* Enumerate alias groups */
862
863 static NTSTATUS cmd_samr_enum_als_groups(struct cli_state *cli, 
864                                          TALLOC_CTX *mem_ctx,
865                                          int argc, const char **argv) 
866 {
867         POLICY_HND connect_pol, domain_pol;
868         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
869         uint32 start_idx, size, num_als_groups, i;
870         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
871         struct acct_info *als_groups;
872         DOM_SID global_sid_Builtin;
873         BOOL got_connect_pol = False, got_domain_pol = False;
874
875         string_to_sid(&global_sid_Builtin, "S-1-5-32");
876
877         if ((argc < 2) || (argc > 3)) {
878                 printf("Usage: %s builtin|domain [access mask]\n", argv[0]);
879                 return NT_STATUS_OK;
880         }
881         
882         if (argc > 2)
883                 sscanf(argv[2], "%x", &access_mask);
884
885         /* Get sam policy handle */
886
887         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
888                                    &connect_pol);
889
890         if (!NT_STATUS_IS_OK(result))
891                 goto done;
892
893         got_connect_pol = True;
894
895         /* Get domain policy handle */
896
897         if (StrCaseCmp(argv[1], "domain")==0)
898                 result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
899                                               access_mask,
900                                               &domain_sid, &domain_pol);
901         else if (StrCaseCmp(argv[1], "builtin")==0)
902                 result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
903                                               access_mask,
904                                               &global_sid_Builtin, &domain_pol);
905         else
906                 return NT_STATUS_OK;
907
908         if (!NT_STATUS_IS_OK(result))
909                 goto done;
910
911         got_domain_pol = True;
912
913         /* Enumerate alias groups */
914
915         start_idx = 0;
916         size = 0xffff;          /* Number of groups to retrieve */
917
918         do {
919                 result = cli_samr_enum_als_groups(
920                         cli, mem_ctx, &domain_pol, &start_idx, size,
921                         &als_groups, &num_als_groups);
922
923                 if (NT_STATUS_IS_OK(result) ||
924                     NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES)) {
925
926                         for (i = 0; i < num_als_groups; i++)
927                                 printf("group:[%s] rid:[0x%x]\n", 
928                                        als_groups[i].acct_name,
929                                        als_groups[i].rid);
930                 }
931         } while (NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES));
932
933  done:
934         if (got_domain_pol)
935                 cli_samr_close(cli, mem_ctx, &domain_pol);
936         
937         if (got_connect_pol)
938                 cli_samr_close(cli, mem_ctx, &connect_pol);
939         
940         return result;
941 }
942
943 /* Query alias membership */
944
945 static NTSTATUS cmd_samr_query_aliasmem(struct cli_state *cli, 
946                                         TALLOC_CTX *mem_ctx,
947                                         int argc, const char **argv) 
948 {
949         POLICY_HND connect_pol, domain_pol, alias_pol;
950         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
951         uint32 alias_rid, num_members, i;
952         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
953         DOM_SID *alias_sids;
954         DOM_SID global_sid_Builtin;
955         
956         string_to_sid(&global_sid_Builtin, "S-1-5-32");
957
958         if ((argc < 3) || (argc > 4)) {
959                 printf("Usage: %s builtin|domain rid [access mask]\n", argv[0]);
960                 return NT_STATUS_OK;
961         }
962
963         sscanf(argv[2], "%i", &alias_rid);
964         
965         if (argc > 3)
966                 sscanf(argv[3], "%x", &access_mask);
967
968         /* Open SAMR handle */
969
970         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
971                                    &connect_pol);
972
973         if (!NT_STATUS_IS_OK(result))
974                 goto done;
975
976         /* Open handle on domain */
977         
978         if (StrCaseCmp(argv[1], "domain")==0)
979                 result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
980                                               MAXIMUM_ALLOWED_ACCESS,
981                                               &domain_sid, &domain_pol);
982         else if (StrCaseCmp(argv[1], "builtin")==0)
983                 result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
984                                               MAXIMUM_ALLOWED_ACCESS,
985                                               &global_sid_Builtin, &domain_pol);
986         else
987                 return NT_STATUS_OK;
988
989         if (!NT_STATUS_IS_OK(result))
990                 goto done;
991
992         /* Open handle on alias */
993
994         result = cli_samr_open_alias(cli, mem_ctx, &domain_pol,
995                                      access_mask,
996                                      alias_rid, &alias_pol);
997         if (!NT_STATUS_IS_OK(result))
998                 goto done;
999
1000         result = cli_samr_query_aliasmem(cli, mem_ctx, &alias_pol,
1001                                          &num_members, &alias_sids);
1002
1003         if (!NT_STATUS_IS_OK(result))
1004                 goto done;
1005
1006         for (i = 0; i < num_members; i++) {
1007                 fstring sid_str;
1008
1009                 sid_to_string(sid_str, &alias_sids[i]);
1010                 printf("\tsid:[%s]\n", sid_str);
1011         }
1012
1013  done:
1014         return result;
1015 }
1016
1017 /* Query display info */
1018
1019 static NTSTATUS cmd_samr_query_dispinfo(struct cli_state *cli, 
1020                                         TALLOC_CTX *mem_ctx,
1021                                         int argc, const char **argv) 
1022 {
1023         POLICY_HND connect_pol, domain_pol;
1024         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1025         uint32 start_idx=0, max_entries=250, max_size = 0xffff, num_entries, i;
1026         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1027         uint32 info_level = 1;
1028         SAM_DISPINFO_CTR ctr;
1029         SAM_DISPINFO_1 info1;
1030         SAM_DISPINFO_2 info2;
1031         SAM_DISPINFO_3 info3;
1032         SAM_DISPINFO_4 info4;
1033         SAM_DISPINFO_5 info5;
1034         int loop_count = 0;
1035         BOOL got_params = False; /* Use get_query_dispinfo_params() or not? */
1036
1037         if (argc > 5) {
1038                 printf("Usage: %s [info level] [start index] [max entries] [max size] [access mask]\n", argv[0]);
1039                 return NT_STATUS_OK;
1040         }
1041
1042         if (argc >= 2)
1043                 sscanf(argv[1], "%i", &info_level);
1044         
1045         if (argc >= 3)
1046                 sscanf(argv[2], "%i", &start_idx);
1047         
1048         if (argc >= 4) {
1049                 sscanf(argv[3], "%i", &max_entries);
1050                 got_params = True;
1051         }
1052         
1053         if (argc >= 5) {
1054                 sscanf(argv[4], "%i", &max_size);
1055                 got_params = True;
1056         }
1057         
1058         if (argc >= 6)
1059                 sscanf(argv[5], "%x", &access_mask);
1060
1061         /* Get sam policy handle */
1062
1063         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1064                                    &connect_pol);
1065
1066         if (!NT_STATUS_IS_OK(result))
1067                 goto done;
1068
1069         /* Get domain policy handle */
1070
1071         result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
1072                                       access_mask, 
1073                                       &domain_sid, &domain_pol);
1074
1075         if (!NT_STATUS_IS_OK(result))
1076                 goto done;
1077
1078         /* Query display info */
1079
1080         ZERO_STRUCT(ctr);
1081         ZERO_STRUCT(info1);
1082         
1083         switch (info_level) {
1084         case 1:
1085                 ZERO_STRUCT(info1);
1086                 ctr.sam.info1 = &info1;
1087                 break;
1088         case 2:
1089                 ZERO_STRUCT(info2);
1090                 ctr.sam.info2 = &info2;
1091                 break;
1092         case 3:
1093                 ZERO_STRUCT(info3);
1094                 ctr.sam.info3 = &info3;
1095                 break;
1096         case 4:
1097                 ZERO_STRUCT(info4);
1098                 ctr.sam.info4 = &info4;
1099                 break;
1100         case 5:
1101                 ZERO_STRUCT(info5);
1102                 ctr.sam.info5 = &info5;
1103                 break;
1104         }
1105
1106
1107         while(1) {
1108
1109                 if (!got_params)
1110                         get_query_dispinfo_params(
1111                                 loop_count, &max_entries, &max_size);
1112                 
1113                 result = cli_samr_query_dispinfo(cli, mem_ctx, &domain_pol,
1114                                                  &start_idx, info_level,
1115                                                  &num_entries, max_entries, 
1116                                                  max_size, &ctr);
1117
1118                 loop_count++;
1119
1120                 if (!NT_STATUS_IS_OK(result) && !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) 
1121                         break;
1122
1123                 if (num_entries == 0) 
1124                         break;
1125
1126                 for (i = 0; i < num_entries; i++) {
1127                         switch (info_level) {
1128                         case 1:
1129                                 display_sam_info_1(&ctr.sam.info1->sam[i], &ctr.sam.info1->str[i]);
1130                                 break;
1131                         case 2:
1132                                 display_sam_info_2(&ctr.sam.info2->sam[i], &ctr.sam.info2->str[i]);
1133                                 break;
1134                         case 3:
1135                                 display_sam_info_3(&ctr.sam.info3->sam[i], &ctr.sam.info3->str[i]);
1136                                 break;
1137                         case 4:
1138                                 display_sam_info_4(&ctr.sam.info4->sam[i], &ctr.sam.info4->str[i]);
1139                                 break;
1140                         case 5:
1141                                 display_sam_info_5(&ctr.sam.info5->sam[i], &ctr.sam.info5->str[i]);
1142                                 break;
1143                         }
1144                 }
1145         }
1146
1147  done:
1148         return result;
1149 }
1150
1151 /* Query domain info */
1152
1153 static NTSTATUS cmd_samr_query_dominfo(struct cli_state *cli, 
1154                                        TALLOC_CTX *mem_ctx,
1155                                        int argc, const char **argv) 
1156 {
1157         POLICY_HND connect_pol, domain_pol;
1158         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1159         uint32 switch_level = 2;
1160         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1161         SAM_UNK_CTR ctr;
1162
1163         if (argc > 2) {
1164                 printf("Usage: %s [info level] [access mask]\n", argv[0]);
1165                 return NT_STATUS_OK;
1166         }
1167
1168         if (argc > 1)
1169                 sscanf(argv[1], "%i", &switch_level);
1170         
1171         if (argc > 2)
1172                 sscanf(argv[2], "%x", &access_mask);
1173
1174         /* Get sam policy handle */
1175
1176         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1177                                    &connect_pol);
1178
1179         if (!NT_STATUS_IS_OK(result))
1180                 goto done;
1181
1182         /* Get domain policy handle */
1183
1184         result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
1185                                       access_mask,
1186                                       &domain_sid, &domain_pol);
1187
1188         if (!NT_STATUS_IS_OK(result))
1189                 goto done;
1190
1191         /* Query domain info */
1192
1193         result = cli_samr_query_dom_info(cli, mem_ctx, &domain_pol,
1194                                          switch_level, &ctr);
1195
1196         if (!NT_STATUS_IS_OK(result))
1197                 goto done;
1198
1199         /* Display domain info */
1200
1201         switch (switch_level) {
1202         case 1:
1203                 display_sam_unk_info_1(&ctr.info.inf1);
1204                 break;
1205         case 2:
1206                 display_sam_unk_info_2(&ctr.info.inf2);
1207                 break;
1208         case 7:
1209                 display_sam_unk_info_7(&ctr.info.inf7);
1210                 break;
1211         case 8:
1212                 display_sam_unk_info_8(&ctr.info.inf8);
1213                 break;
1214         case 12:
1215                 display_sam_unk_info_12(&ctr.info.inf12);
1216                 break;
1217         default:
1218                 printf("cannot display domain info for switch value %d\n",
1219                        switch_level);
1220                 break;
1221         }
1222
1223  done:
1224  
1225         cli_samr_close(cli, mem_ctx, &domain_pol);
1226         cli_samr_close(cli, mem_ctx, &connect_pol);
1227         return result;
1228 }
1229
1230 /* Create domain user */
1231
1232 static NTSTATUS cmd_samr_create_dom_user(struct cli_state *cli, 
1233                                          TALLOC_CTX *mem_ctx,
1234                                          int argc, const char **argv) 
1235 {
1236         POLICY_HND connect_pol, domain_pol, user_pol;
1237         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1238         const char *acct_name;
1239         uint16 acb_info;
1240         uint32 unknown, user_rid;
1241         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1242
1243         if ((argc < 2) || (argc > 3)) {
1244                 printf("Usage: %s username [access mask]\n", argv[0]);
1245                 return NT_STATUS_OK;
1246         }
1247
1248         acct_name = argv[1];
1249         
1250         if (argc > 2)
1251                 sscanf(argv[2], "%x", &access_mask);
1252
1253         /* Get sam policy handle */
1254
1255         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1256                                    &connect_pol);
1257
1258         if (!NT_STATUS_IS_OK(result))
1259                 goto done;
1260
1261         /* Get domain policy handle */
1262
1263         result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
1264                                       access_mask,
1265                                       &domain_sid, &domain_pol);
1266
1267         if (!NT_STATUS_IS_OK(result))
1268                 goto done;
1269
1270         /* Create domain user */
1271
1272         acb_info = ACB_NORMAL;
1273         unknown = 0xe005000b; /* No idea what this is - a permission mask? */
1274
1275         result = cli_samr_create_dom_user(cli, mem_ctx, &domain_pol,
1276                                           acct_name, acb_info, unknown,
1277                                           &user_pol, &user_rid);
1278
1279         if (!NT_STATUS_IS_OK(result))
1280                 goto done;
1281
1282         result = cli_samr_close(cli, mem_ctx, &user_pol);
1283         if (!NT_STATUS_IS_OK(result)) goto done;
1284
1285         result = cli_samr_close(cli, mem_ctx, &domain_pol);
1286         if (!NT_STATUS_IS_OK(result)) goto done;
1287
1288         result = cli_samr_close(cli, mem_ctx, &connect_pol);
1289         if (!NT_STATUS_IS_OK(result)) goto done;
1290
1291  done:
1292         return result;
1293 }
1294
1295 /* Create domain group */
1296
1297 static NTSTATUS cmd_samr_create_dom_group(struct cli_state *cli, 
1298                                           TALLOC_CTX *mem_ctx,
1299                                           int argc, const char **argv) 
1300 {
1301         POLICY_HND connect_pol, domain_pol, group_pol;
1302         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1303         const char *grp_name;
1304         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1305
1306         if ((argc < 2) || (argc > 3)) {
1307                 printf("Usage: %s groupname [access mask]\n", argv[0]);
1308                 return NT_STATUS_OK;
1309         }
1310
1311         grp_name = argv[1];
1312         
1313         if (argc > 2)
1314                 sscanf(argv[2], "%x", &access_mask);
1315
1316         /* Get sam policy handle */
1317
1318         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1319                                    &connect_pol);
1320
1321         if (!NT_STATUS_IS_OK(result))
1322                 goto done;
1323
1324         /* Get domain policy handle */
1325
1326         result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
1327                                       access_mask,
1328                                       &domain_sid, &domain_pol);
1329
1330         if (!NT_STATUS_IS_OK(result))
1331                 goto done;
1332
1333         /* Create domain user */
1334
1335         result = cli_samr_create_dom_group(cli, mem_ctx, &domain_pol,
1336                                            grp_name, MAXIMUM_ALLOWED_ACCESS,
1337                                            &group_pol);
1338
1339         if (!NT_STATUS_IS_OK(result))
1340                 goto done;
1341
1342         result = cli_samr_close(cli, mem_ctx, &group_pol);
1343         if (!NT_STATUS_IS_OK(result)) goto done;
1344
1345         result = cli_samr_close(cli, mem_ctx, &domain_pol);
1346         if (!NT_STATUS_IS_OK(result)) goto done;
1347
1348         result = cli_samr_close(cli, mem_ctx, &connect_pol);
1349         if (!NT_STATUS_IS_OK(result)) goto done;
1350
1351  done:
1352         return result;
1353 }
1354
1355 /* Lookup sam names */
1356
1357 static NTSTATUS cmd_samr_lookup_names(struct cli_state *cli, 
1358                                       TALLOC_CTX *mem_ctx,
1359                                       int argc, const char **argv) 
1360 {
1361         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1362         POLICY_HND connect_pol, domain_pol;
1363         uint32 flags = 0x000003e8; /* Unknown */
1364         uint32 num_rids, num_names, *name_types, *rids;
1365         const char **names;
1366         int i;
1367         DOM_SID global_sid_Builtin;
1368
1369         string_to_sid(&global_sid_Builtin, "S-1-5-32");
1370
1371         if (argc < 3) {
1372                 printf("Usage: %s  domain|builtin name1 [name2 [name3] [...]]\n", argv[0]);
1373                 printf("check on the domain SID: S-1-5-21-x-y-z\n");
1374                 printf("or check on the builtin SID: S-1-5-32\n");
1375                 return NT_STATUS_OK;
1376         }
1377
1378         /* Get sam policy and domain handles */
1379
1380         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1381                                    &connect_pol);
1382
1383         if (!NT_STATUS_IS_OK(result))
1384                 goto done;
1385
1386         if (StrCaseCmp(argv[1], "domain")==0)
1387                 result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
1388                                               MAXIMUM_ALLOWED_ACCESS,
1389                                               &domain_sid, &domain_pol);
1390         else if (StrCaseCmp(argv[1], "builtin")==0)
1391                 result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
1392                                               MAXIMUM_ALLOWED_ACCESS,
1393                                               &global_sid_Builtin, &domain_pol);
1394         else
1395                 return NT_STATUS_OK;
1396
1397         if (!NT_STATUS_IS_OK(result))
1398                 goto done;
1399
1400         /* Look up names */
1401
1402         num_names = argc - 2;
1403         names = TALLOC_ARRAY(mem_ctx, const char *, num_names);
1404
1405         for (i = 0; i < argc - 2; i++)
1406                 names[i] = argv[i + 2];
1407
1408         result = cli_samr_lookup_names(cli, mem_ctx, &domain_pol,
1409                                        flags, num_names, names,
1410                                        &num_rids, &rids, &name_types);
1411
1412         if (!NT_STATUS_IS_OK(result))
1413                 goto done;
1414
1415         /* Display results */
1416
1417         for (i = 0; i < num_names; i++)
1418                 printf("name %s: 0x%x (%d)\n", names[i], rids[i], 
1419                        name_types[i]);
1420
1421  done:
1422         return result;
1423 }
1424
1425 /* Lookup sam rids */
1426
1427 static NTSTATUS cmd_samr_lookup_rids(struct cli_state *cli, 
1428                                      TALLOC_CTX *mem_ctx,
1429                                      int argc, const char **argv) 
1430 {
1431         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1432         POLICY_HND connect_pol, domain_pol;
1433         uint32 num_rids, num_names, *rids, *name_types;
1434         char **names;
1435         int i;
1436
1437         if (argc < 2) {
1438                 printf("Usage: %s rid1 [rid2 [rid3] [...]]\n", argv[0]);
1439                 return NT_STATUS_OK;
1440         }
1441
1442         /* Get sam policy and domain handles */
1443
1444         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1445                                    &connect_pol);
1446
1447         if (!NT_STATUS_IS_OK(result))
1448                 goto done;
1449
1450         result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
1451                                       MAXIMUM_ALLOWED_ACCESS,
1452                                       &domain_sid, &domain_pol);
1453
1454         if (!NT_STATUS_IS_OK(result))
1455                 goto done;
1456
1457         /* Look up rids */
1458
1459         num_rids = argc - 1;
1460         rids = TALLOC_ARRAY(mem_ctx, uint32, num_rids);
1461
1462         for (i = 0; i < argc - 1; i++)
1463                 sscanf(argv[i + 1], "%i", &rids[i]);
1464
1465         result = cli_samr_lookup_rids(cli, mem_ctx, &domain_pol, num_rids, rids,
1466                                       &num_names, &names, &name_types);
1467
1468         if (!NT_STATUS_IS_OK(result) &&
1469             !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED))
1470                 goto done;
1471
1472         /* Display results */
1473
1474         for (i = 0; i < num_names; i++)
1475                 printf("rid 0x%x: %s (%d)\n", rids[i], names[i], name_types[i]);
1476
1477  done:
1478         return result;
1479 }
1480
1481 /* Delete domain user */
1482
1483 static NTSTATUS cmd_samr_delete_dom_user(struct cli_state *cli, 
1484                                          TALLOC_CTX *mem_ctx,
1485                                          int argc, const char **argv) 
1486 {
1487         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1488         POLICY_HND connect_pol, domain_pol, user_pol;
1489         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1490
1491         if ((argc < 2) || (argc > 3)) {
1492                 printf("Usage: %s username\n", argv[0]);
1493                 return NT_STATUS_OK;
1494         }
1495         
1496         if (argc > 2)
1497                 sscanf(argv[2], "%x", &access_mask);
1498
1499         /* Get sam policy and domain handles */
1500
1501         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1502                                    &connect_pol);
1503
1504         if (!NT_STATUS_IS_OK(result))
1505                 goto done;
1506
1507         result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
1508                                       MAXIMUM_ALLOWED_ACCESS,
1509                                       &domain_sid, &domain_pol);
1510
1511         if (!NT_STATUS_IS_OK(result))
1512                 goto done;
1513
1514         /* Get handle on user */
1515
1516         {
1517                 uint32 *user_rids, num_rids, *name_types;
1518                 uint32 flags = 0x000003e8; /* Unknown */
1519
1520                 result = cli_samr_lookup_names(cli, mem_ctx, &domain_pol,
1521                                                flags, 1, (const char **)&argv[1],
1522                                                &num_rids, &user_rids,
1523                                                &name_types);
1524
1525                 if (!NT_STATUS_IS_OK(result))
1526                         goto done;
1527
1528                 result = cli_samr_open_user(cli, mem_ctx, &domain_pol,
1529                                             access_mask,
1530                                             user_rids[0], &user_pol);
1531
1532                 if (!NT_STATUS_IS_OK(result))
1533                         goto done;
1534         }
1535
1536         /* Delete user */
1537
1538         result = cli_samr_delete_dom_user(cli, mem_ctx, &user_pol);
1539
1540         if (!NT_STATUS_IS_OK(result))
1541                 goto done;
1542
1543         /* Display results */
1544
1545  done:
1546         return result;
1547 }
1548
1549 /**********************************************************************
1550  * Query user security object 
1551  */
1552 static NTSTATUS cmd_samr_query_sec_obj(struct cli_state *cli, 
1553                                     TALLOC_CTX *mem_ctx,
1554                                     int argc, const char **argv) 
1555 {
1556         POLICY_HND connect_pol, domain_pol, user_pol, *pol;
1557         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1558         uint32 info_level = 4;
1559         fstring server;
1560         uint32 user_rid = 0;
1561         TALLOC_CTX *ctx = NULL;
1562         SEC_DESC_BUF *sec_desc_buf=NULL;
1563         BOOL domain = False;
1564
1565         ctx=talloc_init("cmd_samr_query_sec_obj");
1566         
1567         if ((argc < 1) || (argc > 2)) {
1568                 printf("Usage: %s [rid|-d]\n", argv[0]);
1569                 printf("\tSpecify rid for security on user, -d for security on domain\n");
1570                 return NT_STATUS_OK;
1571         }
1572         
1573         if (argc > 1) {
1574                 if (strcmp(argv[1], "-d") == 0)
1575                         domain = True;
1576                 else
1577                         sscanf(argv[1], "%i", &user_rid);
1578         }
1579         
1580         slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->desthost);
1581         strupper_m(server);
1582         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
1583                                    &connect_pol);
1584
1585         if (!NT_STATUS_IS_OK(result))
1586                 goto done;
1587
1588         if (domain || user_rid)
1589                 result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
1590                                               MAXIMUM_ALLOWED_ACCESS,
1591                                               &domain_sid, &domain_pol);
1592
1593         if (!NT_STATUS_IS_OK(result))
1594                 goto done;
1595
1596         if (user_rid)
1597                 result = cli_samr_open_user(cli, mem_ctx, &domain_pol,
1598                                             MAXIMUM_ALLOWED_ACCESS,
1599                                             user_rid, &user_pol);
1600
1601         if (!NT_STATUS_IS_OK(result))
1602                 goto done;
1603
1604         /* Pick which query pol to use */
1605
1606         pol = &connect_pol;
1607
1608         if (domain)
1609                 pol = &domain_pol;
1610
1611         if (user_rid)
1612                 pol = &user_pol;
1613
1614         /* Query SAM security object */
1615
1616         result = cli_samr_query_sec_obj(cli, mem_ctx, pol, info_level, ctx, 
1617                                         &sec_desc_buf);
1618
1619         if (!NT_STATUS_IS_OK(result))
1620                 goto done;
1621
1622         display_sec_desc(sec_desc_buf->sec);
1623         
1624 done:
1625         talloc_destroy(ctx);
1626         return result;
1627 }
1628
1629 static NTSTATUS cmd_samr_get_dom_pwinfo(struct cli_state *cli, 
1630                                         TALLOC_CTX *mem_ctx,
1631                                         int argc, const char **argv) 
1632 {
1633         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1634         uint16 unk_0, unk_1;
1635
1636         if (argc != 1) {
1637                 printf("Usage: %s\n", argv[0]);
1638                 return NT_STATUS_OK;
1639         }
1640
1641         result = cli_samr_get_dom_pwinfo(cli, mem_ctx, &unk_0, &unk_1) ;
1642         
1643         if (NT_STATUS_IS_OK(result)) {
1644                 printf("unk_0 = 0x%08x\n", unk_0);
1645                 printf("unk_1 = 0x%08x\n", unk_1);
1646         }
1647
1648         return result;
1649 }
1650
1651 /* Look up domain name */
1652
1653 static NTSTATUS cmd_samr_lookup_domain(struct cli_state *cli, 
1654                                        TALLOC_CTX *mem_ctx,
1655                                        int argc, const char **argv) 
1656 {
1657         POLICY_HND connect_pol, domain_pol;
1658         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1659         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1660         fstring domain_name,sid_string;
1661         DOM_SID sid;
1662         
1663         if (argc != 2) {
1664                 printf("Usage: %s domain_name\n", argv[0]);
1665                 return NT_STATUS_OK;
1666         }
1667         
1668         sscanf(argv[1], "%s", domain_name);
1669         
1670         result = try_samr_connects(cli, mem_ctx, access_mask, &connect_pol);
1671         
1672         if (!NT_STATUS_IS_OK(result))
1673                 goto done;
1674
1675         result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
1676                                       access_mask, &domain_sid, &domain_pol);
1677
1678         if (!NT_STATUS_IS_OK(result))
1679                 goto done;
1680         
1681         result = cli_samr_lookup_domain(
1682                 cli, mem_ctx, &connect_pol, domain_name, &sid);
1683
1684         sid_to_string(sid_string,&sid);
1685  
1686         if (NT_STATUS_IS_OK(result)) 
1687                 printf("SAMR_LOOKUP_DOMAIN: Domain Name: %s Domain SID: %s\n",
1688                        domain_name,sid_string);
1689
1690 done:
1691         return result;
1692 }
1693
1694
1695 /* List of commands exported by this module */
1696
1697 struct cmd_set samr_commands[] = {
1698
1699         { "SAMR" },
1700
1701         { "queryuser",  RPC_RTYPE_NTSTATUS, cmd_samr_query_user,                NULL, PI_SAMR,  "Query user info",         "" },
1702         { "querygroup",         RPC_RTYPE_NTSTATUS, cmd_samr_query_group,               NULL, PI_SAMR,  "Query group info",        "" },
1703         { "queryusergroups",    RPC_RTYPE_NTSTATUS, cmd_samr_query_usergroups,  NULL, PI_SAMR,  "Query user groups",       "" },
1704         { "queryuseraliases",   RPC_RTYPE_NTSTATUS, cmd_samr_query_useraliases,         NULL, PI_SAMR,  "Query user aliases",      "" },
1705         { "querygroupmem",      RPC_RTYPE_NTSTATUS, cmd_samr_query_groupmem,    NULL, PI_SAMR,  "Query group membership",  "" },
1706         { "queryaliasmem",      RPC_RTYPE_NTSTATUS, cmd_samr_query_aliasmem,    NULL, PI_SAMR,  "Query alias membership",  "" },
1707         { "querydispinfo",      RPC_RTYPE_NTSTATUS, cmd_samr_query_dispinfo,    NULL, PI_SAMR,  "Query display info",      "" },
1708         { "querydominfo",       RPC_RTYPE_NTSTATUS, cmd_samr_query_dominfo,     NULL, PI_SAMR,  "Query domain info",       "" },
1709         { "enumdomusers",      RPC_RTYPE_NTSTATUS, cmd_samr_enum_dom_users,       NULL, PI_SAMR,        "Enumerate domain users", "" },
1710         { "enumdomgroups",      RPC_RTYPE_NTSTATUS, cmd_samr_enum_dom_groups,       NULL, PI_SAMR,      "Enumerate domain groups", "" },
1711         { "enumalsgroups",      RPC_RTYPE_NTSTATUS, cmd_samr_enum_als_groups,       NULL, PI_SAMR,      "Enumerate alias groups",  "" },
1712
1713         { "createdomuser",      RPC_RTYPE_NTSTATUS, cmd_samr_create_dom_user,       NULL, PI_SAMR,      "Create domain user",      "" },
1714         { "createdomgroup",     RPC_RTYPE_NTSTATUS, cmd_samr_create_dom_group,      NULL, PI_SAMR,      "Create domain group",     "" },
1715         { "samlookupnames",     RPC_RTYPE_NTSTATUS, cmd_samr_lookup_names,          NULL, PI_SAMR,      "Look up names",           "" },
1716         { "samlookuprids",      RPC_RTYPE_NTSTATUS, cmd_samr_lookup_rids,           NULL, PI_SAMR,      "Look up names",           "" },
1717         { "deletedomuser",      RPC_RTYPE_NTSTATUS, cmd_samr_delete_dom_user,       NULL, PI_SAMR,      "Delete domain user",      "" },
1718         { "samquerysecobj",     RPC_RTYPE_NTSTATUS, cmd_samr_query_sec_obj,         NULL, PI_SAMR, "Query SAMR security object",   "" },
1719         { "getdompwinfo",       RPC_RTYPE_NTSTATUS, cmd_samr_get_dom_pwinfo,        NULL, PI_SAMR, "Retrieve domain password info", "" },
1720
1721         { "lookupdomain",       RPC_RTYPE_NTSTATUS, cmd_samr_lookup_domain,         NULL, PI_SAMR, "Lookup Domain Name", "" },
1722         { NULL }
1723 };