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