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