Let the carnage begin....
[metze/old/v3-2-winbind-ndr.git] / source / 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 delete an alias membership */
1069
1070 static NTSTATUS cmd_samr_delete_alias(struct rpc_pipe_client *cli, 
1071                                       TALLOC_CTX *mem_ctx,
1072                                       int argc, const char **argv) 
1073 {
1074         POLICY_HND connect_pol, domain_pol, alias_pol;
1075         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1076         uint32 alias_rid;
1077         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1078
1079         if (argc != 3) {
1080                 printf("Usage: %s builtin|domain [rid|name]\n", argv[0]);
1081                 return NT_STATUS_OK;
1082         }
1083
1084         alias_rid = strtoul(argv[2], NULL, 10);
1085         
1086         /* Open SAMR handle */
1087
1088         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1089                                    &connect_pol);
1090
1091         if (!NT_STATUS_IS_OK(result))
1092                 goto done;
1093
1094         /* Open handle on domain */
1095         
1096         if (StrCaseCmp(argv[1], "domain")==0)
1097                 result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
1098                                               MAXIMUM_ALLOWED_ACCESS,
1099                                               &domain_sid, &domain_pol);
1100         else if (StrCaseCmp(argv[1], "builtin")==0)
1101                 result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
1102                                               MAXIMUM_ALLOWED_ACCESS,
1103                                               &global_sid_Builtin, &domain_pol);
1104         else
1105                 return NT_STATUS_INVALID_PARAMETER;
1106
1107         if (!NT_STATUS_IS_OK(result))
1108                 goto done;
1109
1110         /* Open handle on alias */
1111
1112         result = rpccli_samr_open_alias(cli, mem_ctx, &domain_pol,
1113                                      access_mask,
1114                                      alias_rid, &alias_pol);
1115         if (!NT_STATUS_IS_OK(result) && (alias_rid == 0)) {
1116                 /* Probably this was a user name, try lookupnames */
1117                 uint32 num_rids;
1118                 uint32 *rids, *types;
1119                 
1120                 result = rpccli_samr_lookup_names(cli, mem_ctx, &domain_pol,
1121                                                   1000, 1, &argv[2],
1122                                                   &num_rids, &rids,
1123                                                   &types);
1124
1125                 if (NT_STATUS_IS_OK(result)) {
1126                         result = rpccli_samr_open_alias(cli, mem_ctx,
1127                                                        &domain_pol,
1128                                                        access_mask,
1129                                                        rids[0], &alias_pol);
1130                 }
1131         }
1132
1133         result = rpccli_samr_delete_dom_alias(cli, mem_ctx, &alias_pol);
1134
1135         if (!NT_STATUS_IS_OK(result))
1136                 goto done;
1137
1138         rpccli_samr_close(cli, mem_ctx, &domain_pol);
1139         rpccli_samr_close(cli, mem_ctx, &connect_pol);
1140  done:
1141         return result;
1142 }
1143
1144 /* Query display info */
1145
1146 static NTSTATUS cmd_samr_query_dispinfo(struct rpc_pipe_client *cli, 
1147                                         TALLOC_CTX *mem_ctx,
1148                                         int argc, const char **argv) 
1149 {
1150         POLICY_HND connect_pol, domain_pol;
1151         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1152         uint32 start_idx=0, max_entries=250, max_size = 0xffff, num_entries, i;
1153         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1154         uint32 info_level = 1;
1155         SAM_DISPINFO_CTR ctr;
1156         SAM_DISPINFO_1 info1;
1157         SAM_DISPINFO_2 info2;
1158         SAM_DISPINFO_3 info3;
1159         SAM_DISPINFO_4 info4;
1160         SAM_DISPINFO_5 info5;
1161         int loop_count = 0;
1162         BOOL got_params = False; /* Use get_query_dispinfo_params() or not? */
1163
1164         if (argc > 5) {
1165                 printf("Usage: %s [info level] [start index] [max entries] [max size] [access mask]\n", argv[0]);
1166                 return NT_STATUS_OK;
1167         }
1168
1169         if (argc >= 2)
1170                 sscanf(argv[1], "%i", &info_level);
1171         
1172         if (argc >= 3)
1173                 sscanf(argv[2], "%i", &start_idx);
1174         
1175         if (argc >= 4) {
1176                 sscanf(argv[3], "%i", &max_entries);
1177                 got_params = True;
1178         }
1179         
1180         if (argc >= 5) {
1181                 sscanf(argv[4], "%i", &max_size);
1182                 got_params = True;
1183         }
1184         
1185         if (argc >= 6)
1186                 sscanf(argv[5], "%x", &access_mask);
1187
1188         /* Get sam policy handle */
1189
1190         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1191                                    &connect_pol);
1192
1193         if (!NT_STATUS_IS_OK(result))
1194                 goto done;
1195
1196         /* Get domain policy handle */
1197
1198         result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
1199                                       access_mask, 
1200                                       &domain_sid, &domain_pol);
1201
1202         if (!NT_STATUS_IS_OK(result))
1203                 goto done;
1204
1205         /* Query display info */
1206
1207         ZERO_STRUCT(ctr);
1208         ZERO_STRUCT(info1);
1209         
1210         switch (info_level) {
1211         case 1:
1212                 ZERO_STRUCT(info1);
1213                 ctr.sam.info1 = &info1;
1214                 break;
1215         case 2:
1216                 ZERO_STRUCT(info2);
1217                 ctr.sam.info2 = &info2;
1218                 break;
1219         case 3:
1220                 ZERO_STRUCT(info3);
1221                 ctr.sam.info3 = &info3;
1222                 break;
1223         case 4:
1224                 ZERO_STRUCT(info4);
1225                 ctr.sam.info4 = &info4;
1226                 break;
1227         case 5:
1228                 ZERO_STRUCT(info5);
1229                 ctr.sam.info5 = &info5;
1230                 break;
1231         }
1232
1233
1234         do {
1235
1236                 if (!got_params)
1237                         get_query_dispinfo_params(
1238                                 loop_count, &max_entries, &max_size);
1239                 
1240                 result = rpccli_samr_query_dispinfo(cli, mem_ctx, &domain_pol,
1241                                                  &start_idx, info_level,
1242                                                  &num_entries, max_entries, 
1243                                                  max_size, &ctr);
1244
1245                 loop_count++;
1246
1247                 if (NT_STATUS_IS_ERR(result))
1248                         break;
1249
1250                 if (num_entries == 0) 
1251                         break;
1252
1253                 for (i = 0; i < num_entries; i++) {
1254                         switch (info_level) {
1255                         case 1:
1256                                 display_sam_info_1(&ctr.sam.info1->sam[i], &ctr.sam.info1->str[i]);
1257                                 break;
1258                         case 2:
1259                                 display_sam_info_2(&ctr.sam.info2->sam[i], &ctr.sam.info2->str[i]);
1260                                 break;
1261                         case 3:
1262                                 display_sam_info_3(&ctr.sam.info3->sam[i], &ctr.sam.info3->str[i]);
1263                                 break;
1264                         case 4:
1265                                 display_sam_info_4(&ctr.sam.info4->sam[i], &ctr.sam.info4->str[i]);
1266                                 break;
1267                         case 5:
1268                                 display_sam_info_5(&ctr.sam.info5->sam[i], &ctr.sam.info5->str[i]);
1269                                 break;
1270                         }
1271                 }
1272         } while ( NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
1273
1274         rpccli_samr_close(cli, mem_ctx, &domain_pol);
1275         rpccli_samr_close(cli, mem_ctx, &connect_pol);
1276  done:
1277         return result;
1278 }
1279
1280 /* Query domain info */
1281
1282 static NTSTATUS cmd_samr_query_dominfo(struct rpc_pipe_client *cli, 
1283                                        TALLOC_CTX *mem_ctx,
1284                                        int argc, const char **argv) 
1285 {
1286         POLICY_HND connect_pol, domain_pol;
1287         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1288         uint32 switch_level = 2;
1289         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1290         SAM_UNK_CTR ctr;
1291
1292         if (argc > 2) {
1293                 printf("Usage: %s [info level] [access mask]\n", argv[0]);
1294                 return NT_STATUS_OK;
1295         }
1296
1297         if (argc > 1)
1298                 sscanf(argv[1], "%i", &switch_level);
1299         
1300         if (argc > 2)
1301                 sscanf(argv[2], "%x", &access_mask);
1302
1303         /* Get sam policy handle */
1304
1305         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1306                                    &connect_pol);
1307
1308         if (!NT_STATUS_IS_OK(result))
1309                 goto done;
1310
1311         /* Get domain policy handle */
1312
1313         result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
1314                                       access_mask,
1315                                       &domain_sid, &domain_pol);
1316
1317         if (!NT_STATUS_IS_OK(result))
1318                 goto done;
1319
1320         /* Query domain info */
1321
1322         result = rpccli_samr_query_dom_info(cli, mem_ctx, &domain_pol,
1323                                          switch_level, &ctr);
1324
1325         if (!NT_STATUS_IS_OK(result))
1326                 goto done;
1327
1328         /* Display domain info */
1329
1330         switch (switch_level) {
1331         case 1:
1332                 display_sam_unk_info_1(&ctr.info.inf1);
1333                 break;
1334         case 2:
1335                 display_sam_unk_info_2(&ctr.info.inf2);
1336                 break;
1337         case 7:
1338                 display_sam_unk_info_7(&ctr.info.inf7);
1339                 break;
1340         case 8:
1341                 display_sam_unk_info_8(&ctr.info.inf8);
1342                 break;
1343         case 12:
1344                 display_sam_unk_info_12(&ctr.info.inf12);
1345                 break;
1346         default:
1347                 printf("cannot display domain info for switch value %d\n",
1348                        switch_level);
1349                 break;
1350         }
1351
1352  done:
1353  
1354         rpccli_samr_close(cli, mem_ctx, &domain_pol);
1355         rpccli_samr_close(cli, mem_ctx, &connect_pol);
1356         return result;
1357 }
1358
1359 /* Create domain user */
1360
1361 static NTSTATUS cmd_samr_create_dom_user(struct rpc_pipe_client *cli, 
1362                                          TALLOC_CTX *mem_ctx,
1363                                          int argc, const char **argv) 
1364 {
1365         POLICY_HND connect_pol, domain_pol, user_pol;
1366         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1367         const char *acct_name;
1368         uint16 acb_info;
1369         uint32 unknown, user_rid;
1370         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1371
1372         if ((argc < 2) || (argc > 3)) {
1373                 printf("Usage: %s username [access mask]\n", argv[0]);
1374                 return NT_STATUS_OK;
1375         }
1376
1377         acct_name = argv[1];
1378         
1379         if (argc > 2)
1380                 sscanf(argv[2], "%x", &access_mask);
1381
1382         /* Get sam policy handle */
1383
1384         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1385                                    &connect_pol);
1386
1387         if (!NT_STATUS_IS_OK(result))
1388                 goto done;
1389
1390         /* Get domain policy handle */
1391
1392         result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
1393                                       access_mask,
1394                                       &domain_sid, &domain_pol);
1395
1396         if (!NT_STATUS_IS_OK(result))
1397                 goto done;
1398
1399         /* Create domain user */
1400
1401         acb_info = ACB_NORMAL;
1402         unknown = 0xe005000b; /* No idea what this is - a permission mask? */
1403
1404         result = rpccli_samr_create_dom_user(cli, mem_ctx, &domain_pol,
1405                                           acct_name, acb_info, unknown,
1406                                           &user_pol, &user_rid);
1407
1408         if (!NT_STATUS_IS_OK(result))
1409                 goto done;
1410
1411         result = rpccli_samr_close(cli, mem_ctx, &user_pol);
1412         if (!NT_STATUS_IS_OK(result)) goto done;
1413
1414         result = rpccli_samr_close(cli, mem_ctx, &domain_pol);
1415         if (!NT_STATUS_IS_OK(result)) goto done;
1416
1417         result = rpccli_samr_close(cli, mem_ctx, &connect_pol);
1418         if (!NT_STATUS_IS_OK(result)) goto done;
1419
1420  done:
1421         return result;
1422 }
1423
1424 /* Create domain group */
1425
1426 static NTSTATUS cmd_samr_create_dom_group(struct rpc_pipe_client *cli, 
1427                                           TALLOC_CTX *mem_ctx,
1428                                           int argc, const char **argv) 
1429 {
1430         POLICY_HND connect_pol, domain_pol, group_pol;
1431         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1432         const char *grp_name;
1433         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1434
1435         if ((argc < 2) || (argc > 3)) {
1436                 printf("Usage: %s groupname [access mask]\n", argv[0]);
1437                 return NT_STATUS_OK;
1438         }
1439
1440         grp_name = argv[1];
1441         
1442         if (argc > 2)
1443                 sscanf(argv[2], "%x", &access_mask);
1444
1445         /* Get sam policy handle */
1446
1447         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1448                                    &connect_pol);
1449
1450         if (!NT_STATUS_IS_OK(result))
1451                 goto done;
1452
1453         /* Get domain policy handle */
1454
1455         result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
1456                                       access_mask,
1457                                       &domain_sid, &domain_pol);
1458
1459         if (!NT_STATUS_IS_OK(result))
1460                 goto done;
1461
1462         /* Create domain user */
1463
1464         result = rpccli_samr_create_dom_group(cli, mem_ctx, &domain_pol,
1465                                            grp_name, MAXIMUM_ALLOWED_ACCESS,
1466                                            &group_pol);
1467
1468         if (!NT_STATUS_IS_OK(result))
1469                 goto done;
1470
1471         result = rpccli_samr_close(cli, mem_ctx, &group_pol);
1472         if (!NT_STATUS_IS_OK(result)) goto done;
1473
1474         result = rpccli_samr_close(cli, mem_ctx, &domain_pol);
1475         if (!NT_STATUS_IS_OK(result)) goto done;
1476
1477         result = rpccli_samr_close(cli, mem_ctx, &connect_pol);
1478         if (!NT_STATUS_IS_OK(result)) goto done;
1479
1480  done:
1481         return result;
1482 }
1483
1484 /* Create domain alias */
1485
1486 static NTSTATUS cmd_samr_create_dom_alias(struct rpc_pipe_client *cli, 
1487                                           TALLOC_CTX *mem_ctx,
1488                                           int argc, const char **argv) 
1489 {
1490         POLICY_HND connect_pol, domain_pol, alias_pol;
1491         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1492         const char *alias_name;
1493         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1494
1495         if ((argc < 2) || (argc > 3)) {
1496                 printf("Usage: %s aliasname [access mask]\n", argv[0]);
1497                 return NT_STATUS_OK;
1498         }
1499
1500         alias_name = argv[1];
1501         
1502         if (argc > 2)
1503                 sscanf(argv[2], "%x", &access_mask);
1504
1505         /* Get sam policy handle */
1506
1507         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1508                                    &connect_pol);
1509
1510         if (!NT_STATUS_IS_OK(result))
1511                 goto done;
1512
1513         /* Get domain policy handle */
1514
1515         result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
1516                                          access_mask,
1517                                          &domain_sid, &domain_pol);
1518
1519         if (!NT_STATUS_IS_OK(result))
1520                 goto done;
1521
1522         /* Create domain user */
1523
1524         result = rpccli_samr_create_dom_alias(cli, mem_ctx, &domain_pol,
1525                                               alias_name, &alias_pol);
1526
1527         if (!NT_STATUS_IS_OK(result))
1528                 goto done;
1529
1530         result = rpccli_samr_close(cli, mem_ctx, &alias_pol);
1531         if (!NT_STATUS_IS_OK(result)) goto done;
1532
1533         result = rpccli_samr_close(cli, mem_ctx, &domain_pol);
1534         if (!NT_STATUS_IS_OK(result)) goto done;
1535
1536         result = rpccli_samr_close(cli, mem_ctx, &connect_pol);
1537         if (!NT_STATUS_IS_OK(result)) goto done;
1538
1539  done:
1540         return result;
1541 }
1542
1543 /* Lookup sam names */
1544
1545 static NTSTATUS cmd_samr_lookup_names(struct rpc_pipe_client *cli, 
1546                                       TALLOC_CTX *mem_ctx,
1547                                       int argc, const char **argv) 
1548 {
1549         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1550         POLICY_HND connect_pol, domain_pol;
1551         uint32 flags = 0x000003e8; /* Unknown */
1552         uint32 num_rids, num_names, *name_types, *rids;
1553         const char **names;
1554         int i;
1555
1556         if (argc < 3) {
1557                 printf("Usage: %s  domain|builtin name1 [name2 [name3] [...]]\n", argv[0]);
1558                 printf("check on the domain SID: S-1-5-21-x-y-z\n");
1559                 printf("or check on the builtin SID: S-1-5-32\n");
1560                 return NT_STATUS_OK;
1561         }
1562
1563         /* Get sam policy and domain handles */
1564
1565         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1566                                    &connect_pol);
1567
1568         if (!NT_STATUS_IS_OK(result))
1569                 goto done;
1570
1571         if (StrCaseCmp(argv[1], "domain")==0)
1572                 result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
1573                                               MAXIMUM_ALLOWED_ACCESS,
1574                                               &domain_sid, &domain_pol);
1575         else if (StrCaseCmp(argv[1], "builtin")==0)
1576                 result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
1577                                               MAXIMUM_ALLOWED_ACCESS,
1578                                               &global_sid_Builtin, &domain_pol);
1579         else
1580                 return NT_STATUS_OK;
1581
1582         if (!NT_STATUS_IS_OK(result))
1583                 goto done;
1584
1585         /* Look up names */
1586
1587         num_names = argc - 2;
1588         names = TALLOC_ARRAY(mem_ctx, const char *, num_names);
1589
1590         for (i = 0; i < argc - 2; i++)
1591                 names[i] = argv[i + 2];
1592
1593         result = rpccli_samr_lookup_names(cli, mem_ctx, &domain_pol,
1594                                        flags, num_names, names,
1595                                        &num_rids, &rids, &name_types);
1596
1597         if (!NT_STATUS_IS_OK(result))
1598                 goto done;
1599
1600         /* Display results */
1601
1602         for (i = 0; i < num_names; i++)
1603                 printf("name %s: 0x%x (%d)\n", names[i], rids[i], 
1604                        name_types[i]);
1605
1606         rpccli_samr_close(cli, mem_ctx, &domain_pol);
1607         rpccli_samr_close(cli, mem_ctx, &connect_pol);
1608  done:
1609         return result;
1610 }
1611
1612 /* Lookup sam rids */
1613
1614 static NTSTATUS cmd_samr_lookup_rids(struct rpc_pipe_client *cli, 
1615                                      TALLOC_CTX *mem_ctx,
1616                                      int argc, const char **argv) 
1617 {
1618         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1619         POLICY_HND connect_pol, domain_pol;
1620         uint32 num_rids, num_names, *rids, *name_types;
1621         char **names;
1622         int i;
1623
1624         if (argc < 3) {
1625                 printf("Usage: %s domain|builtin rid1 [rid2 [rid3] [...]]\n", argv[0]);
1626                 return NT_STATUS_OK;
1627         }
1628
1629         /* Get sam policy and domain handles */
1630
1631         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1632                                    &connect_pol);
1633
1634         if (!NT_STATUS_IS_OK(result))
1635                 goto done;
1636
1637         if (StrCaseCmp(argv[1], "domain")==0)
1638                 result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
1639                                               MAXIMUM_ALLOWED_ACCESS,
1640                                               &domain_sid, &domain_pol);
1641         else if (StrCaseCmp(argv[1], "builtin")==0)
1642                 result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
1643                                               MAXIMUM_ALLOWED_ACCESS,
1644                                               &global_sid_Builtin, &domain_pol);
1645         else
1646                 return NT_STATUS_OK;
1647
1648         if (!NT_STATUS_IS_OK(result))
1649                 goto done;
1650
1651         /* Look up rids */
1652
1653         num_rids = argc - 2;
1654         rids = TALLOC_ARRAY(mem_ctx, uint32, num_rids);
1655
1656         for (i = 0; i < argc - 2; i++)
1657                 sscanf(argv[i + 2], "%i", &rids[i]);
1658
1659         result = rpccli_samr_lookup_rids(cli, mem_ctx, &domain_pol, num_rids, rids,
1660                                       &num_names, &names, &name_types);
1661
1662         if (!NT_STATUS_IS_OK(result) &&
1663             !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED))
1664                 goto done;
1665
1666         /* Display results */
1667
1668         for (i = 0; i < num_names; i++)
1669                 printf("rid 0x%x: %s (%d)\n", rids[i], names[i], name_types[i]);
1670
1671         rpccli_samr_close(cli, mem_ctx, &domain_pol);
1672         rpccli_samr_close(cli, mem_ctx, &connect_pol);
1673  done:
1674         return result;
1675 }
1676
1677 /* Delete domain user */
1678
1679 static NTSTATUS cmd_samr_delete_dom_user(struct rpc_pipe_client *cli, 
1680                                          TALLOC_CTX *mem_ctx,
1681                                          int argc, const char **argv) 
1682 {
1683         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1684         POLICY_HND connect_pol, domain_pol, user_pol;
1685         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1686
1687         if ((argc < 2) || (argc > 3)) {
1688                 printf("Usage: %s username\n", argv[0]);
1689                 return NT_STATUS_OK;
1690         }
1691         
1692         if (argc > 2)
1693                 sscanf(argv[2], "%x", &access_mask);
1694
1695         /* Get sam policy and domain handles */
1696
1697         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1698                                    &connect_pol);
1699
1700         if (!NT_STATUS_IS_OK(result))
1701                 goto done;
1702
1703         result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
1704                                       MAXIMUM_ALLOWED_ACCESS,
1705                                       &domain_sid, &domain_pol);
1706
1707         if (!NT_STATUS_IS_OK(result))
1708                 goto done;
1709
1710         /* Get handle on user */
1711
1712         {
1713                 uint32 *user_rids, num_rids, *name_types;
1714                 uint32 flags = 0x000003e8; /* Unknown */
1715
1716                 result = rpccli_samr_lookup_names(cli, mem_ctx, &domain_pol,
1717                                                flags, 1, (const char **)&argv[1],
1718                                                &num_rids, &user_rids,
1719                                                &name_types);
1720
1721                 if (!NT_STATUS_IS_OK(result))
1722                         goto done;
1723
1724                 result = rpccli_samr_open_user(cli, mem_ctx, &domain_pol,
1725                                             access_mask,
1726                                             user_rids[0], &user_pol);
1727
1728                 if (!NT_STATUS_IS_OK(result))
1729                         goto done;
1730         }
1731
1732         /* Delete user */
1733
1734         result = rpccli_samr_delete_dom_user(cli, mem_ctx, &user_pol);
1735
1736         if (!NT_STATUS_IS_OK(result))
1737                 goto done;
1738
1739         /* Display results */
1740
1741         rpccli_samr_close(cli, mem_ctx, &user_pol);
1742         rpccli_samr_close(cli, mem_ctx, &domain_pol);
1743         rpccli_samr_close(cli, mem_ctx, &connect_pol);
1744
1745  done:
1746         return result;
1747 }
1748
1749 /**********************************************************************
1750  * Query user security object 
1751  */
1752 static NTSTATUS cmd_samr_query_sec_obj(struct rpc_pipe_client *cli, 
1753                                     TALLOC_CTX *mem_ctx,
1754                                     int argc, const char **argv) 
1755 {
1756         POLICY_HND connect_pol, domain_pol, user_pol, *pol;
1757         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1758         uint32 info_level = 4;
1759         fstring server;
1760         uint32 user_rid = 0;
1761         TALLOC_CTX *ctx = NULL;
1762         SEC_DESC_BUF *sec_desc_buf=NULL;
1763         BOOL domain = False;
1764
1765         ctx=talloc_init("cmd_samr_query_sec_obj");
1766         
1767         if ((argc < 1) || (argc > 2)) {
1768                 printf("Usage: %s [rid|-d]\n", argv[0]);
1769                 printf("\tSpecify rid for security on user, -d for security on domain\n");
1770                 return NT_STATUS_OK;
1771         }
1772         
1773         if (argc > 1) {
1774                 if (strcmp(argv[1], "-d") == 0)
1775                         domain = True;
1776                 else
1777                         sscanf(argv[1], "%i", &user_rid);
1778         }
1779         
1780         slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost);
1781         strupper_m(server);
1782         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
1783                                    &connect_pol);
1784
1785         if (!NT_STATUS_IS_OK(result))
1786                 goto done;
1787
1788         if (domain || user_rid)
1789                 result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
1790                                               MAXIMUM_ALLOWED_ACCESS,
1791                                               &domain_sid, &domain_pol);
1792
1793         if (!NT_STATUS_IS_OK(result))
1794                 goto done;
1795
1796         if (user_rid)
1797                 result = rpccli_samr_open_user(cli, mem_ctx, &domain_pol,
1798                                             MAXIMUM_ALLOWED_ACCESS,
1799                                             user_rid, &user_pol);
1800
1801         if (!NT_STATUS_IS_OK(result))
1802                 goto done;
1803
1804         /* Pick which query pol to use */
1805
1806         pol = &connect_pol;
1807
1808         if (domain)
1809                 pol = &domain_pol;
1810
1811         if (user_rid)
1812                 pol = &user_pol;
1813
1814         /* Query SAM security object */
1815
1816         result = rpccli_samr_query_sec_obj(cli, mem_ctx, pol, info_level, ctx, 
1817                                         &sec_desc_buf);
1818
1819         if (!NT_STATUS_IS_OK(result))
1820                 goto done;
1821
1822         display_sec_desc(sec_desc_buf->sec);
1823         
1824         rpccli_samr_close(cli, mem_ctx, &user_pol);
1825         rpccli_samr_close(cli, mem_ctx, &domain_pol);
1826         rpccli_samr_close(cli, mem_ctx, &connect_pol);
1827 done:
1828         talloc_destroy(ctx);
1829         return result;
1830 }
1831
1832 static NTSTATUS cmd_samr_get_dom_pwinfo(struct rpc_pipe_client *cli, 
1833                                         TALLOC_CTX *mem_ctx,
1834                                         int argc, const char **argv) 
1835 {
1836         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1837         uint16 min_pwd_length;
1838         uint32 password_properties;
1839
1840         if (argc != 1) {
1841                 printf("Usage: %s\n", argv[0]);
1842                 return NT_STATUS_OK;
1843         }
1844
1845         result = rpccli_samr_get_dom_pwinfo(cli, mem_ctx, &min_pwd_length, &password_properties) ;
1846         
1847         if (NT_STATUS_IS_OK(result)) {
1848                 printf("min_pwd_length: %d\n", min_pwd_length);
1849                 printf("password_properties: 0x%08x\n", password_properties);
1850                 
1851                 if (password_properties & DOMAIN_PASSWORD_COMPLEX)
1852                         printf("\tDOMAIN_PASSWORD_COMPLEX\n");
1853                         
1854                 if (password_properties & DOMAIN_PASSWORD_NO_ANON_CHANGE)
1855                         printf("\tDOMAIN_PASSWORD_NO_ANON_CHANGE\n");
1856                         
1857                 if (password_properties & DOMAIN_PASSWORD_NO_CLEAR_CHANGE)
1858                         printf("\tDOMAIN_PASSWORD_NO_CLEAR_CHANGE\n");
1859                         
1860                 if (password_properties & DOMAIN_LOCKOUT_ADMINS)
1861                         printf("\tDOMAIN_LOCKOUT_ADMINS\n");
1862                         
1863                 if (password_properties & DOMAIN_PASSWORD_STORE_CLEARTEXT)
1864                         printf("\tDOMAIN_PASSWORD_STORE_CLEARTEXT\n");
1865                         
1866                 if (password_properties & DOMAIN_REFUSE_PASSWORD_CHANGE)
1867                         printf("\tDOMAIN_REFUSE_PASSWORD_CHANGE\n");
1868         }
1869
1870         return result;
1871 }
1872
1873 /* Look up domain name */
1874
1875 static NTSTATUS cmd_samr_lookup_domain(struct rpc_pipe_client *cli, 
1876                                        TALLOC_CTX *mem_ctx,
1877                                        int argc, const char **argv) 
1878 {
1879         POLICY_HND connect_pol, domain_pol;
1880         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1881         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1882         fstring domain_name,sid_string;
1883         DOM_SID sid;
1884         
1885         if (argc != 2) {
1886                 printf("Usage: %s domain_name\n", argv[0]);
1887                 return NT_STATUS_OK;
1888         }
1889         
1890         sscanf(argv[1], "%s", domain_name);
1891         
1892         result = try_samr_connects(cli, mem_ctx, access_mask, &connect_pol);
1893         
1894         if (!NT_STATUS_IS_OK(result))
1895                 goto done;
1896
1897         result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
1898                                       access_mask, &domain_sid, &domain_pol);
1899
1900         if (!NT_STATUS_IS_OK(result))
1901                 goto done;
1902         
1903         result = rpccli_samr_lookup_domain(
1904                 cli, mem_ctx, &connect_pol, domain_name, &sid);
1905
1906         sid_to_string(sid_string,&sid);
1907  
1908         if (NT_STATUS_IS_OK(result)) 
1909                 printf("SAMR_LOOKUP_DOMAIN: Domain Name: %s Domain SID: %s\n",
1910                        domain_name,sid_string);
1911
1912         rpccli_samr_close(cli, mem_ctx, &domain_pol);
1913         rpccli_samr_close(cli, mem_ctx, &connect_pol);
1914 done:
1915         return result;
1916 }
1917
1918
1919 /* List of commands exported by this module */
1920
1921 struct cmd_set samr_commands[] = {
1922
1923         { "SAMR" },
1924
1925         { "queryuser",  RPC_RTYPE_NTSTATUS, cmd_samr_query_user,                NULL, PI_SAMR, NULL,    "Query user info",         "" },
1926         { "querygroup",         RPC_RTYPE_NTSTATUS, cmd_samr_query_group,               NULL, PI_SAMR, NULL,    "Query group info",        "" },
1927         { "queryusergroups",    RPC_RTYPE_NTSTATUS, cmd_samr_query_usergroups,  NULL, PI_SAMR, NULL,    "Query user groups",       "" },
1928         { "queryuseraliases",   RPC_RTYPE_NTSTATUS, cmd_samr_query_useraliases,         NULL, PI_SAMR, NULL,    "Query user aliases",      "" },
1929         { "querygroupmem",      RPC_RTYPE_NTSTATUS, cmd_samr_query_groupmem,    NULL, PI_SAMR, NULL,    "Query group membership",  "" },
1930         { "queryaliasmem",      RPC_RTYPE_NTSTATUS, cmd_samr_query_aliasmem,    NULL, PI_SAMR, NULL,    "Query alias membership",  "" },
1931         { "deletealias",        RPC_RTYPE_NTSTATUS, cmd_samr_delete_alias,      NULL, PI_SAMR, NULL,    "Delete an alias",  "" },
1932         { "querydispinfo",      RPC_RTYPE_NTSTATUS, cmd_samr_query_dispinfo,    NULL, PI_SAMR, NULL,    "Query display info",      "" },
1933         { "querydominfo",       RPC_RTYPE_NTSTATUS, cmd_samr_query_dominfo,     NULL, PI_SAMR, NULL,    "Query domain info",       "" },
1934         { "enumdomusers",      RPC_RTYPE_NTSTATUS, cmd_samr_enum_dom_users,       NULL, PI_SAMR, NULL,  "Enumerate domain users", "" },
1935         { "enumdomgroups",      RPC_RTYPE_NTSTATUS, cmd_samr_enum_dom_groups,       NULL, PI_SAMR, NULL,        "Enumerate domain groups", "" },
1936         { "enumalsgroups",      RPC_RTYPE_NTSTATUS, cmd_samr_enum_als_groups,       NULL, PI_SAMR, NULL,        "Enumerate alias groups",  "" },
1937
1938         { "createdomuser",      RPC_RTYPE_NTSTATUS, cmd_samr_create_dom_user,       NULL, PI_SAMR, NULL,        "Create domain user",      "" },
1939         { "createdomgroup",     RPC_RTYPE_NTSTATUS, cmd_samr_create_dom_group,      NULL, PI_SAMR, NULL,        "Create domain group",     "" },
1940         { "createdomalias",     RPC_RTYPE_NTSTATUS, cmd_samr_create_dom_alias,      NULL, PI_SAMR, NULL,        "Create domain alias",     "" },
1941         { "samlookupnames",     RPC_RTYPE_NTSTATUS, cmd_samr_lookup_names,          NULL, PI_SAMR, NULL,        "Look up names",           "" },
1942         { "samlookuprids",      RPC_RTYPE_NTSTATUS, cmd_samr_lookup_rids,           NULL, PI_SAMR, NULL,        "Look up names",           "" },
1943         { "deletedomuser",      RPC_RTYPE_NTSTATUS, cmd_samr_delete_dom_user,       NULL, PI_SAMR, NULL,        "Delete domain user",      "" },
1944         { "samquerysecobj",     RPC_RTYPE_NTSTATUS, cmd_samr_query_sec_obj,         NULL, PI_SAMR, NULL, "Query SAMR security object",   "" },
1945         { "getdompwinfo",       RPC_RTYPE_NTSTATUS, cmd_samr_get_dom_pwinfo,        NULL, PI_SAMR, NULL, "Retrieve domain password info", "" },
1946
1947         { "lookupdomain",       RPC_RTYPE_NTSTATUS, cmd_samr_lookup_domain,         NULL, PI_SAMR, NULL, "Lookup Domain Name", "" },
1948         { NULL }
1949 };