0ba7d0871e2f58756067dbc770053841428c6299
[samba.git] / source3 / rpc_server / srv_samr.c
1
2 /* 
3  *  Unix SMB/Netbios implementation.
4  *  Version 1.9.
5  *  RPC Pipe client / server routines
6  *  Copyright (C) Andrew Tridgell              1992-1997,
7  *  Copyright (C) Luke Kenneth Casson Leighton 1996-1997,
8  *  Copyright (C) Paul Ashton                       1997.
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
26 #include "includes.h"
27 #include "nterr.h"
28
29 extern int DEBUGLEVEL;
30
31 extern fstring global_sam_name;
32 extern pstring global_myname;
33 extern DOM_SID global_sam_sid;
34 extern DOM_SID global_sid_S_1_1;
35 extern DOM_SID global_sid_S_1_5_20;
36
37 extern rid_name domain_group_rids[];
38 extern rid_name domain_alias_rids[];
39 extern rid_name builtin_alias_rids[];
40
41 /*******************************************************************
42   This next function should be replaced with something that
43   dynamically returns the correct user info..... JRA.
44  ********************************************************************/
45
46 static BOOL get_sampwd_entries(SAM_USER_INFO_21 *pw_buf,
47                                 int start_idx,
48                                 int *total_entries, int *num_entries,
49                                 int max_num_entries,
50                                 uint16 acb_mask)
51 {
52         void *vp = NULL;
53         struct sam_passwd *pwd = NULL;
54
55         (*num_entries) = 0;
56         (*total_entries) = 0;
57
58         if (pw_buf == NULL) return False;
59
60         vp = startsmbpwent(False);
61         if (!vp)
62         {
63                 DEBUG(0, ("get_sampwd_entries: Unable to open SMB password database.\n"));
64                 return False;
65         }
66
67         while (((pwd = getsam21pwent(vp)) != NULL) && (*num_entries) < max_num_entries)
68         {
69                 int user_name_len;
70
71                 if (start_idx > 0)
72                 {
73                         /* skip the requested number of entries.
74                            not very efficient, but hey...
75                          */
76                         start_idx--;
77                         continue;
78                 }
79
80                 user_name_len = strlen(pwd->nt_name);
81                 make_unistr2(&(pw_buf[(*num_entries)].uni_user_name), pwd->nt_name, user_name_len);
82                 make_uni_hdr(&(pw_buf[(*num_entries)].hdr_user_name), user_name_len, 
83                                user_name_len, 1);
84                 pw_buf[(*num_entries)].user_rid = pwd->user_rid;
85                 bzero( pw_buf[(*num_entries)].nt_pwd , 16);
86
87                 /* Now check if the NT compatible password is available. */
88                 if (pwd->smb_nt_passwd != NULL)
89                 {
90                         memcpy( pw_buf[(*num_entries)].nt_pwd , pwd->smb_nt_passwd, 16);
91                 }
92
93                 pw_buf[(*num_entries)].acb_info = (uint16)pwd->acct_ctrl;
94
95                 DEBUG(5, ("entry idx: %d user %s, rid 0x%x, acb %x",
96                           (*num_entries), pwd->nt_name,
97                           pwd->user_rid, pwd->acct_ctrl));
98
99                 if (acb_mask == 0 || IS_BITS_SET_SOME(pwd->acct_ctrl, acb_mask))
100                 {
101                         DEBUG(5,(" acb_mask %x accepts\n", acb_mask));
102                         (*num_entries)++;
103                 }
104                 else
105                 {
106                         DEBUG(5,(" acb_mask %x rejects\n", acb_mask));
107                 }
108
109                 (*total_entries)++;
110         }
111
112         endsmbpwent(vp);
113
114         return (*num_entries) > 0;
115 }
116
117 /*******************************************************************
118  samr_reply_unknown_1
119  ********************************************************************/
120 static void samr_reply_close_hnd(SAMR_Q_CLOSE_HND *q_u,
121                                 prs_struct *rdata)
122 {
123         SAMR_R_CLOSE_HND r_u;
124
125         /* set up the SAMR unknown_1 response */
126         bzero(r_u.pol.data, POL_HND_SIZE);
127
128         /* close the policy handle */
129         if (close_lsa_policy_hnd(&(q_u->pol)))
130         {
131                 r_u.status = 0;
132         }
133         else
134         {
135                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_INVALID;
136         }
137
138         DEBUG(5,("samr_reply_close_hnd: %d\n", __LINE__));
139
140         /* store the response in the SMB stream */
141         samr_io_r_close_hnd("", &r_u, rdata, 0);
142
143         DEBUG(5,("samr_reply_close_hnd: %d\n", __LINE__));
144
145 }
146
147 /*******************************************************************
148  api_samr_close_hnd
149  ********************************************************************/
150 static void api_samr_close_hnd( uint16 vuid, prs_struct *data, prs_struct *rdata)
151 {
152         SAMR_Q_CLOSE_HND q_u;
153
154         /* grab the samr unknown 1 */
155         samr_io_q_close_hnd("", &q_u, data, 0);
156
157         /* construct reply.  always indicate success */
158         samr_reply_close_hnd(&q_u, rdata);
159 }
160
161
162 /*******************************************************************
163  samr_reply_open_domain
164  ********************************************************************/
165 static void samr_reply_open_domain(SAMR_Q_OPEN_DOMAIN *q_u,
166                                 prs_struct *rdata)
167 {
168         SAMR_R_OPEN_DOMAIN r_u;
169         BOOL pol_open = False;
170
171         r_u.status = 0x0;
172
173         /* find the connection policy handle. */
174         if (r_u.status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->connect_pol)) == -1))
175         {
176                 r_u.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
177         }
178
179         /* get a (unique) handle.  open a policy on it. */
180         if (r_u.status == 0x0 && !(pol_open = open_lsa_policy_hnd(&(r_u.domain_pol))))
181         {
182                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
183         }
184
185         /* associate the domain SID with the (unique) handle. */
186         if (r_u.status == 0x0 && !set_lsa_policy_samr_sid(&(r_u.domain_pol), &(q_u->dom_sid.sid)))
187         {
188                 /* oh, whoops.  don't know what error message to return, here */
189                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
190         }
191
192         if (r_u.status != 0 && pol_open)
193         {
194                 close_lsa_policy_hnd(&(r_u.domain_pol));
195         }
196
197         DEBUG(5,("samr_open_domain: %d\n", __LINE__));
198
199         /* store the response in the SMB stream */
200         samr_io_r_open_domain("", &r_u, rdata, 0);
201
202         DEBUG(5,("samr_open_domain: %d\n", __LINE__));
203
204 }
205
206 /*******************************************************************
207  api_samr_open_domain
208  ********************************************************************/
209 static void api_samr_open_domain( uint16 vuid, prs_struct *data, prs_struct *rdata)
210 {
211         SAMR_Q_OPEN_DOMAIN q_u;
212
213         /* grab the samr open */
214         samr_io_q_open_domain("", &q_u, data, 0);
215
216         /* construct reply.  always indicate success */
217         samr_reply_open_domain(&q_u, rdata);
218 }
219
220
221 /*******************************************************************
222  samr_reply_unknown_2c
223  ********************************************************************/
224 static void samr_reply_unknown_2c(SAMR_Q_UNKNOWN_2C *q_u,
225                                 prs_struct *rdata)
226 {
227         SAMR_R_UNKNOWN_2C r_u;
228         uint32 status = 0x0;
229
230         /* find the policy handle.  open a policy on it. */
231         if (status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->user_pol)) == -1))
232         {
233                 status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
234         }
235
236         /* find the user's rid */
237         if ((status == 0x0) && (get_lsa_policy_samr_rid(&(q_u->user_pol)) == 0xffffffff))
238         {
239                 status = NT_STATUS_OBJECT_TYPE_MISMATCH;
240         }
241
242         make_samr_r_unknown_2c(&r_u, status);
243
244         DEBUG(5,("samr_unknown_2c: %d\n", __LINE__));
245
246         /* store the response in the SMB stream */
247         samr_io_r_unknown_2c("", &r_u, rdata, 0);
248
249         DEBUG(5,("samr_unknown_2c: %d\n", __LINE__));
250
251 }
252
253 /*******************************************************************
254  api_samr_unknown_2c
255  ********************************************************************/
256 static void api_samr_unknown_2c( uint16 vuid, prs_struct *data, prs_struct *rdata)
257 {
258         SAMR_Q_UNKNOWN_2C q_u;
259
260         /* grab the samr open */
261         samr_io_q_unknown_2c("", &q_u, data, 0);
262
263         /* construct reply.  always indicate success */
264         samr_reply_unknown_2c(&q_u, rdata);
265 }
266
267
268 /*******************************************************************
269  samr_reply_unknown_3
270  ********************************************************************/
271 static void samr_reply_unknown_3(SAMR_Q_UNKNOWN_3 *q_u,
272                                 prs_struct *rdata)
273 {
274         SAMR_R_UNKNOWN_3 r_u;
275         DOM_SID3 sid[MAX_SAM_SIDS];
276         uint32 rid;
277         uint32 status;
278
279         status = 0x0;
280
281         /* find the policy handle.  open a policy on it. */
282         if (status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->user_pol)) == -1))
283         {
284                 status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
285         }
286
287         /* find the user's rid */
288         if (status == 0x0 && (rid = get_lsa_policy_samr_rid(&(q_u->user_pol))) == 0xffffffff)
289         {
290                 status = NT_STATUS_OBJECT_TYPE_MISMATCH;
291         }
292
293         if (status == 0x0)
294         {
295                 DOM_SID usr_sid;
296
297                 usr_sid = global_sam_sid;
298
299                 SMB_ASSERT_ARRAY(usr_sid.sub_auths, usr_sid.num_auths+1);
300
301                 /*
302                  * Add the user RID.
303                  */
304                 sid_append_rid(&usr_sid, rid);
305                 
306                 /* maybe need another 1 or 2 (S-1-5-0x20-0x220 and S-1-5-20-0x224) */
307                 /* these two are DOMAIN_ADMIN and DOMAIN_ACCT_OP group RIDs */
308                 make_dom_sid3(&(sid[0]), 0x035b, 0x0002, &global_sid_S_1_1);
309                 make_dom_sid3(&(sid[1]), 0x0044, 0x0002, &usr_sid);
310         }
311
312         make_samr_r_unknown_3(&r_u,
313                                 0x0001, 0x8004,
314                                 0x00000014, 0x0002, 0x0070,
315                                 2, sid, status);
316
317         DEBUG(5,("samr_unknown_3: %d\n", __LINE__));
318
319         /* store the response in the SMB stream */
320         samr_io_r_unknown_3("", &r_u, rdata, 0);
321
322         DEBUG(5,("samr_unknown_3: %d\n", __LINE__));
323
324 }
325
326 /*******************************************************************
327  api_samr_unknown_3
328  ********************************************************************/
329 static void api_samr_unknown_3( uint16 vuid, prs_struct *data, prs_struct *rdata)
330 {
331         SAMR_Q_UNKNOWN_3 q_u;
332
333         /* grab the samr open */
334         samr_io_q_unknown_3("", &q_u, data, 0);
335
336         /* construct reply.  always indicate success */
337         samr_reply_unknown_3(&q_u, rdata);
338 }
339
340
341 /*******************************************************************
342  samr_reply_enum_dom_users
343  ********************************************************************/
344 static void samr_reply_enum_dom_users(SAMR_Q_ENUM_DOM_USERS *q_u,
345                                 prs_struct *rdata)
346 {
347         SAMR_R_ENUM_DOM_USERS r_e;
348         SAM_USER_INFO_21 pass[MAX_SAM_ENTRIES];
349         int num_entries;
350         int total_entries;
351
352         r_e.status = 0x0;
353         r_e.total_num_entries = 0;
354
355         /* find the policy handle.  open a policy on it. */
356         if (r_e.status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->pol)) == -1))
357         {
358                 r_e.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
359         }
360
361         DEBUG(5,("samr_reply_enum_dom_users: %d\n", __LINE__));
362
363         become_root(True);
364         get_sampwd_entries(pass, 0, &total_entries, &num_entries, MAX_SAM_ENTRIES, q_u->acb_mask);
365         unbecome_root(True);
366
367         make_samr_r_enum_dom_users(&r_e, total_entries,
368                                    q_u->unknown_0, num_entries,
369                                    pass, r_e.status);
370
371         /* store the response in the SMB stream */
372         samr_io_r_enum_dom_users("", &r_e, rdata, 0);
373
374         DEBUG(5,("samr_enum_dom_users: %d\n", __LINE__));
375
376 }
377
378 /*******************************************************************
379  api_samr_enum_dom_users
380  ********************************************************************/
381 static void api_samr_enum_dom_users( uint16 vuid, prs_struct *data, prs_struct *rdata)
382 {
383         SAMR_Q_ENUM_DOM_USERS q_e;
384
385         /* grab the samr open */
386         samr_io_q_enum_dom_users("", &q_e, data, 0);
387
388         /* construct reply. */
389         samr_reply_enum_dom_users(&q_e, rdata);
390 }
391
392
393 /*******************************************************************
394  samr_reply_enum_dom_groups
395  ********************************************************************/
396 static void samr_reply_enum_dom_groups(SAMR_Q_ENUM_DOM_GROUPS *q_u,
397                                 prs_struct *rdata)
398 {
399         SAMR_R_ENUM_DOM_GROUPS r_e;
400         DOMAIN_GRP *grps = NULL;
401         int num_entries = 0;
402         BOOL got_grps = False;
403         DOM_SID sid;
404         fstring sid_str;
405
406         r_e.status = 0x0;
407         r_e.num_entries = 0;
408
409         /* find the policy handle.  open a policy on it. */
410         if (r_e.status == 0x0 && !get_lsa_policy_samr_sid(&q_u->pol, &sid))
411         {
412                 r_e.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
413         }
414
415         sid_to_string(sid_str, &sid);
416
417         DEBUG(5,("samr_reply_enum_dom_groups: sid %s\n", sid_str));
418
419         if (sid_equal(&sid, &global_sam_sid))
420         {
421                 BOOL ret;
422                 got_grps = True;
423
424                 become_root(True);
425                 ret = enumdomgroups(&grps, &num_entries);
426                 unbecome_root(True);
427
428                 if (!ret)
429                 {
430                         r_e.status = 0xC0000000 | NT_STATUS_NO_MEMORY;
431                 }
432         }
433
434         if (r_e.status == 0x0 &&
435             (sid_equal(&sid, &global_sam_sid) ||
436              sid_equal(&sid, &global_sid_S_1_5_20)))
437         {
438                 char *name;
439                 int i = 0;
440                 got_grps = True;
441
442                 while (num_entries < MAX_SAM_ENTRIES && ((name = domain_group_rids[i].name) != NULL))
443                 {
444                         DOMAIN_GRP tmp_grp;
445
446                         fstrcpy(tmp_grp.name   , name);
447                         fstrcpy(tmp_grp.comment, "");
448                         tmp_grp.rid = domain_group_rids[i].rid;
449                         tmp_grp.attr = 0x7;
450
451                         if (!add_domain_group(&grps, &num_entries, &tmp_grp))
452                         {
453                                 r_e.status = 0xC0000000 | NT_STATUS_NO_MEMORY;
454                                 break;
455                         }
456
457                         i++;
458                 }
459         }
460
461         if (r_e.status == 0 && got_grps)
462         {
463                 make_samr_r_enum_dom_groups(&r_e, q_u->start_idx, num_entries, grps, r_e.status);
464         }
465
466         /* store the response in the SMB stream */
467         samr_io_r_enum_dom_groups("", &r_e, rdata, 0);
468
469         if (grps != NULL)
470         {
471                 free(grps);
472         }
473
474         DEBUG(5,("samr_enum_dom_groups: %d\n", __LINE__));
475 }
476
477 /*******************************************************************
478  api_samr_enum_dom_groups
479  ********************************************************************/
480 static void api_samr_enum_dom_groups( uint16 vuid, prs_struct *data, prs_struct *rdata)
481 {
482         SAMR_Q_ENUM_DOM_GROUPS q_e;
483
484         /* grab the samr open */
485         samr_io_q_enum_dom_groups("", &q_e, data, 0);
486
487         /* construct reply. */
488         samr_reply_enum_dom_groups(&q_e, rdata);
489 }
490
491
492 /*******************************************************************
493  samr_reply_enum_dom_aliases
494  ********************************************************************/
495 static void samr_reply_enum_dom_aliases(SAMR_Q_ENUM_DOM_ALIASES *q_u,
496                                 prs_struct *rdata)
497 {
498         SAMR_R_ENUM_DOM_ALIASES r_e;
499         LOCAL_GRP *alss = NULL;
500         int num_entries = 0;
501         DOM_SID sid;
502         fstring sid_str;
503
504         r_e.status = 0x0;
505         r_e.num_entries = 0;
506
507         /* find the policy handle.  open a policy on it. */
508         if (r_e.status == 0x0 && !get_lsa_policy_samr_sid(&q_u->pol, &sid))
509         {
510                 r_e.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
511         }
512
513         sid_to_string(sid_str, &sid);
514
515         DEBUG(5,("samr_reply_enum_dom_aliases: sid %s\n", sid_str));
516
517         /* well-known aliases */
518         if (sid_equal(&sid, &global_sid_S_1_5_20))
519         {
520                 char *name;
521
522                 while ((name = builtin_alias_rids[num_entries].name) != NULL)
523                 {
524                         LOCAL_GRP tmp_als;
525
526                         fstrcpy(tmp_als.name   , name);
527                         fstrcpy(tmp_als.comment, "");
528                         tmp_als.rid = builtin_alias_rids[num_entries].rid;
529
530                         if (!add_domain_alias(&alss, &num_entries, &tmp_als))
531                         {
532                                 r_e.status = 0xC0000000 | NT_STATUS_NO_MEMORY;
533                                 break;
534                         }
535                 }
536         }
537         else if (sid_equal(&sid, &global_sam_sid))
538         {
539                 BOOL ret;
540                 /* local aliases */
541                 num_entries = 0;
542
543                 become_root(True);
544                 ret = enumdomaliases(&alss, &num_entries);
545                 unbecome_root(True);
546                 if (!ret)
547                 {
548                         r_e.status = 0xC0000000 | NT_STATUS_NO_MEMORY;
549                 }
550         }
551                 
552         if (r_e.status == 0x0)
553         {
554                 make_samr_r_enum_dom_aliases(&r_e, num_entries, alss, r_e.status);
555         }
556
557         /* store the response in the SMB stream */
558         samr_io_r_enum_dom_aliases("", &r_e, rdata, 0);
559
560         if (alss != NULL)
561         {
562                 free(alss);
563         }
564
565         DEBUG(5,("samr_enum_dom_aliases: %d\n", __LINE__));
566
567 }
568
569 /*******************************************************************
570  api_samr_enum_dom_aliases
571  ********************************************************************/
572 static void api_samr_enum_dom_aliases( uint16 vuid, prs_struct *data, prs_struct *rdata)
573 {
574         SAMR_Q_ENUM_DOM_ALIASES q_e;
575
576         /* grab the samr open */
577         samr_io_q_enum_dom_aliases("", &q_e, data, 0);
578
579         /* construct reply. */
580         samr_reply_enum_dom_aliases(&q_e, rdata);
581 }
582
583
584 /*******************************************************************
585  samr_reply_query_dispinfo
586  ********************************************************************/
587 static void samr_reply_query_dispinfo(SAMR_Q_QUERY_DISPINFO *q_u,
588                                 prs_struct *rdata)
589 {
590         SAMR_R_QUERY_DISPINFO r_e;
591         SAM_INFO_CTR ctr;
592         SAM_INFO_1 info1;
593         SAM_INFO_2 info2;
594         SAM_USER_INFO_21 pass[MAX_SAM_ENTRIES];
595         int num_entries = 0;
596         int total_entries = 0;
597         BOOL got_pwds;
598         uint16 switch_level = 0x0;
599
600         ZERO_STRUCT(r_e);
601
602         r_e.status = 0x0;
603
604         DEBUG(5,("samr_reply_query_dispinfo: %d\n", __LINE__));
605
606         /* find the policy handle.  open a policy on it. */
607         if (r_e.status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->pol)) == -1))
608         {
609                 r_e.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
610                 DEBUG(5,("samr_reply_query_dispinfo: invalid handle\n"));
611         }
612
613         if (r_e.status == 0x0)
614         {
615                 become_root(True);
616                 got_pwds = get_sampwd_entries(pass, q_u->start_idx, &total_entries, &num_entries, MAX_SAM_ENTRIES, 0);
617                 unbecome_root(True);
618
619                 switch (q_u->switch_level)
620                 {
621                         case 0x1:
622                         {
623                         
624                                 /* query disp info is for users */
625                                 switch_level = 0x1;
626                                 make_sam_info_1(&info1, ACB_NORMAL,
627                                         q_u->start_idx, num_entries, pass);
628
629                                 ctr.sam.info1 = &info1;
630
631                                 break;
632                         }
633                         case 0x2:
634                         {
635                                 /* query disp info is for servers */
636                                 switch_level = 0x2;
637                                 make_sam_info_2(&info2, ACB_WSTRUST,
638                                         q_u->start_idx, num_entries, pass);
639
640                                 ctr.sam.info2 = &info2;
641
642                                 break;
643                         }
644                 }
645         }
646
647         if (r_e.status == 0 && got_pwds)
648         {
649                 make_samr_r_query_dispinfo(&r_e, switch_level, &ctr, r_e.status);
650         }
651
652         /* store the response in the SMB stream */
653         samr_io_r_query_dispinfo("", &r_e, rdata, 0);
654
655         DEBUG(5,("samr_query_dispinfo: %d\n", __LINE__));
656
657 }
658
659 /*******************************************************************
660  api_samr_query_dispinfo
661  ********************************************************************/
662 static void api_samr_query_dispinfo( uint16 vuid, prs_struct *data, prs_struct *rdata)
663 {
664         SAMR_Q_QUERY_DISPINFO q_e;
665
666         /* grab the samr open */
667         samr_io_q_query_dispinfo("", &q_e, data, 0);
668
669         /* construct reply. */
670         samr_reply_query_dispinfo(&q_e, rdata);
671 }
672
673
674 /*******************************************************************
675  samr_reply_query_aliasinfo
676  ********************************************************************/
677 static void samr_reply_query_aliasinfo(SAMR_Q_QUERY_ALIASINFO *q_u,
678                                 prs_struct *rdata)
679 {
680         SAMR_R_QUERY_ALIASINFO r_e;
681         ALIAS_INFO_CTR ctr;
682         uint32 status = 0x0;
683
684         r_e.ptr = 0;
685
686         /* find the policy handle.  open a policy on it. */
687         if (r_e.status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->pol)) == -1))
688         {
689                 r_e.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
690         }
691
692         DEBUG(5,("samr_reply_query_aliasinfo: %d\n", __LINE__));
693
694         if (status == 0x0)
695         {
696                 if (q_u->switch_level == 3)
697                 {
698                         r_e.ptr = 1;
699                         ctr.switch_value = 3;
700                         make_samr_alias_info3(&ctr.alias.info3, "<account description>");
701                 }
702                 else
703                 {
704                         status = NT_STATUS_INVALID_INFO_CLASS;
705                 }
706         }
707
708         make_samr_r_query_aliasinfo(&r_e, status == 0 ? &ctr : NULL, status);
709
710         /* store the response in the SMB stream */
711         samr_io_r_query_aliasinfo("", &r_e, rdata, 0);
712
713         DEBUG(5,("samr_query_aliasinfo: %d\n", __LINE__));
714
715 }
716
717 /*******************************************************************
718  api_samr_query_aliasinfo
719  ********************************************************************/
720 static void api_samr_query_aliasinfo( uint16 vuid, prs_struct *data, prs_struct *rdata)
721 {
722         SAMR_Q_QUERY_ALIASINFO q_e;
723
724         /* grab the samr open */
725         samr_io_q_query_aliasinfo("", &q_e, data, 0);
726
727         /* construct reply. */
728         samr_reply_query_aliasinfo(&q_e, rdata);
729 }
730
731
732 /*******************************************************************
733  samr_reply_query_useraliases
734  ********************************************************************/
735 static void samr_reply_query_useraliases(SAMR_Q_QUERY_USERALIASES *q_u,
736                                 prs_struct *rdata)
737 {
738         uint32 status = 0;
739
740         LOCAL_GRP *mem_grp = NULL;
741         uint32 *rid = NULL;
742         int num_rids = 0;
743         struct sam_passwd *sam_pass;
744         DOM_SID usr_sid;
745         DOM_SID dom_sid;
746         uint32 user_rid;
747         fstring sam_sid_str;
748         fstring dom_sid_str;
749         fstring usr_sid_str;
750
751         SAMR_R_QUERY_USERALIASES r_u;
752
753         DEBUG(5,("samr_query_useraliases: %d\n", __LINE__));
754
755         /* find the policy handle.  open a policy on it. */
756         if (status == 0x0 && !get_lsa_policy_samr_sid(&q_u->pol, &dom_sid))
757         {
758                 status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
759         }
760         else
761         {
762                 sid_to_string(dom_sid_str, &dom_sid       );
763                 sid_to_string(sam_sid_str, &global_sam_sid);
764         }
765
766         if (status == 0x0)
767         {
768                 usr_sid = q_u->sid[0].sid;
769                 sid_split_rid(&usr_sid, &user_rid);
770                 sid_to_string(usr_sid_str, &usr_sid);
771
772         }
773
774         if (status == 0x0)
775         {
776                 /* find the user account */
777                 become_root(True);
778                 sam_pass = getsam21pwrid(user_rid);
779                 unbecome_root(True);
780
781                 if (sam_pass == NULL)
782                 {
783                         status = 0xC0000000 | NT_STATUS_NO_SUCH_USER;
784                         num_rids = 0;
785                 }
786         }
787
788         if (status == 0x0)
789         {
790                 DEBUG(10,("sid is %s\n", dom_sid_str));
791
792                 if (sid_equal(&dom_sid, &global_sid_S_1_5_20))
793                 {
794                         DEBUG(10,("lookup on S-1-5-20\n"));
795
796                         become_root(True);
797                         getuserbuiltinntnam(sam_pass->nt_name, &mem_grp, &num_rids);
798                         unbecome_root(True);
799                 }
800                 else if (sid_equal(&dom_sid, &usr_sid))
801                 {
802                         DEBUG(10,("lookup on Domain SID\n"));
803
804                         become_root(True);
805                         getuseraliasntnam(sam_pass->nt_name, &mem_grp, &num_rids);
806                         unbecome_root(True);
807                 }
808                 else
809                 {
810                         status = 0xC0000000 | NT_STATUS_NO_SUCH_USER;
811                 }
812         }
813
814         if (status == 0x0 && num_rids > 0)
815         {
816                         rid = malloc(num_rids * sizeof(uint32));
817                         if (mem_grp != NULL && rid != NULL)
818                         {
819                                 int i;
820                                 for (i = 0; i < num_rids; i++)
821                                 {
822                                         rid[i] = mem_grp[i].rid;
823                                 }
824                                 free(mem_grp);
825                 }
826         }
827
828         make_samr_r_query_useraliases(&r_u, num_rids, rid, status);
829
830         /* store the response in the SMB stream */
831         samr_io_r_query_useraliases("", &r_u, rdata, 0);
832
833         if (rid != NULL)
834         {
835                 free(rid);
836         }
837
838         DEBUG(5,("samr_query_useraliases: %d\n", __LINE__));
839
840 }
841
842 /*******************************************************************
843  api_samr_query_useraliases
844  ********************************************************************/
845 static void api_samr_query_useraliases( uint16 vuid, prs_struct *data, prs_struct *rdata)
846 {
847         SAMR_Q_QUERY_USERALIASES q_u;
848
849         /* grab the samr 0x10 */
850         samr_io_q_query_useraliases("", &q_u, data, 0);
851
852         /* construct reply.  always indicate success */
853         samr_reply_query_useraliases(&q_u, rdata);
854 }
855
856 /*******************************************************************
857  samr_reply_query_aliasmem
858  ********************************************************************/
859 static void samr_reply_query_aliasmem(SAMR_Q_QUERY_ALIASMEM *q_u,
860                                 prs_struct *rdata)
861 {
862         uint32 status = 0;
863
864         LOCAL_GRP_MEMBER *mem_grp = NULL;
865         DOM_SID *sid = NULL;
866         int num_sids = 0;
867         DOM_SID alias_sid;
868         uint32 alias_rid;
869         fstring alias_sid_str;
870
871         SAMR_R_QUERY_ALIASMEM r_u;
872
873         DEBUG(5,("samr_query_aliasmem: %d\n", __LINE__));
874
875         /* find the policy handle.  open a policy on it. */
876         if (status == 0x0 && !get_lsa_policy_samr_sid(&q_u->alias_pol, &alias_sid))
877         {
878                 status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
879         }
880         else
881         {
882                 sid_to_string(alias_sid_str, &alias_sid     );
883                 sid_split_rid(&alias_sid, &alias_rid);
884         }
885
886         if (status == 0x0)
887         {
888                 DEBUG(10,("sid is %s\n", alias_sid_str));
889
890                 if (sid_equal(&alias_sid, &global_sid_S_1_5_20))
891                 {
892                         DEBUG(10,("lookup on S-1-5-20\n"));
893
894                         become_root(True);
895                         status = getbuiltinrid(alias_rid, &mem_grp, &num_sids) ? 0xC0000000 | NT_STATUS_NO_SUCH_GROUP : 0x0;
896                         unbecome_root(True);
897                 }
898                 else if (sid_equal(&alias_sid, &global_sam_sid))
899                 {
900                         DEBUG(10,("lookup on Domain SID\n"));
901
902                         become_root(True);
903                         status = getaliasrid(alias_rid, &mem_grp, &num_sids) ? 0xC0000000 | NT_STATUS_NO_SUCH_GROUP : 0x0;
904                         unbecome_root(True);
905                 }
906                 else
907                 {
908                         status = 0xC0000000 | NT_STATUS_NO_SUCH_USER;
909                 }
910         }
911
912         if (status == 0x0 && num_sids > 0)
913         {
914                 sid = malloc(num_sids * sizeof(DOM_SID));
915                 if (mem_grp != NULL && sid != NULL)
916                 {
917                         int i;
918                         for (i = 0; i < num_sids; i++)
919                         {
920                                 sid[i] = mem_grp[i].sid;
921                         }
922                         free(mem_grp);
923                 }
924         }
925
926         make_samr_r_query_aliasmem(&r_u, num_sids, sid, status);
927
928         /* store the response in the SMB stream */
929         samr_io_r_query_aliasmem("", &r_u, rdata, 0);
930
931         if (sid != NULL)
932         {
933                 free(sid);
934         }
935
936         DEBUG(5,("samr_query_aliasmem: %d\n", __LINE__));
937
938 }
939
940 /*******************************************************************
941  api_samr_query_aliasmem
942  ********************************************************************/
943 static void api_samr_query_aliasmem( uint16 vuid, prs_struct *data, prs_struct *rdata)
944 {
945         SAMR_Q_QUERY_ALIASMEM q_u;
946
947         /* grab the samr 0x21 */
948         samr_io_q_query_aliasmem("", &q_u, data, 0);
949
950         /* construct reply.  always indicate success */
951         samr_reply_query_aliasmem(&q_u, rdata);
952 }
953
954 /*******************************************************************
955  samr_reply_lookup_names
956  ********************************************************************/
957 static void samr_reply_lookup_names(SAMR_Q_LOOKUP_NAMES *q_u,
958                                 prs_struct *rdata)
959 {
960         uint32 rid [MAX_SAM_ENTRIES];
961         uint8  type[MAX_SAM_ENTRIES];
962         uint32 status     = 0;
963         int i;
964         int num_rids = q_u->num_rids1;
965
966         SAMR_R_LOOKUP_NAMES r_u;
967
968         DEBUG(5,("samr_lookup_names: %d\n", __LINE__));
969
970         if (num_rids > MAX_SAM_ENTRIES)
971         {
972                 num_rids = MAX_SAM_ENTRIES;
973                 DEBUG(5,("samr_lookup_names: truncating entries to %d\n", num_rids));
974         }
975
976         SMB_ASSERT_ARRAY(q_u->uni_user_name, num_rids);
977
978         for (i = 0; i < num_rids && status == 0; i++)
979         {
980                 DOM_SID sid;
981                 fstring name;
982                 fstrcpy(name, unistrn2(q_u->uni_user_name[i].buffer, q_u->uni_user_name[i].uni_str_len));
983
984                 status = lookup_name(name, &sid, &(type[i]));
985                 if (status == 0x0)
986                 {
987                         sid_split_rid(&sid, &rid[i]);
988                 }
989                 else
990                 {
991                         type[i] = SID_NAME_UNKNOWN;
992                 }
993         }
994
995         make_samr_r_lookup_names(&r_u, num_rids, rid, type, status);
996
997         /* store the response in the SMB stream */
998         samr_io_r_lookup_names("", &r_u, rdata, 0);
999
1000         DEBUG(5,("samr_lookup_names: %d\n", __LINE__));
1001
1002 }
1003
1004 /*******************************************************************
1005  api_samr_lookup_names
1006  ********************************************************************/
1007 static void api_samr_lookup_names( uint16 vuid, prs_struct *data, prs_struct *rdata)
1008 {
1009         SAMR_Q_LOOKUP_NAMES q_u;
1010
1011         /* grab the samr lookup names */
1012         samr_io_q_lookup_names("", &q_u, data, 0);
1013
1014         /* construct reply.  always indicate success */
1015         samr_reply_lookup_names(&q_u, rdata);
1016 }
1017
1018 /*******************************************************************
1019  samr_reply_chgpasswd_user
1020  ********************************************************************/
1021 static void samr_reply_chgpasswd_user(SAMR_Q_CHGPASSWD_USER *q_u,
1022                                 prs_struct *rdata)
1023 {
1024         SAMR_R_CHGPASSWD_USER r_u;
1025         uint32 status = 0x0;
1026         fstring user_name;
1027         fstring wks;
1028
1029         fstrcpy(user_name, unistrn2(q_u->uni_user_name.buffer, q_u->uni_user_name.uni_str_len));
1030         fstrcpy(wks      , unistrn2(q_u->uni_dest_host.buffer, q_u->uni_dest_host.uni_str_len));
1031
1032         DEBUG(5,("samr_chgpasswd_user: user: %s wks: %s\n", user_name, wks));
1033
1034         if (!pass_oem_change(user_name,
1035                              q_u->lm_newpass.pass, q_u->lm_oldhash.hash,
1036                              q_u->nt_newpass.pass, q_u->nt_oldhash.hash))
1037         {
1038                 status = 0xC0000000 | NT_STATUS_WRONG_PASSWORD;
1039         }
1040
1041         make_samr_r_chgpasswd_user(&r_u, status);
1042
1043         /* store the response in the SMB stream */
1044         samr_io_r_chgpasswd_user("", &r_u, rdata, 0);
1045
1046         DEBUG(5,("samr_chgpasswd_user: %d\n", __LINE__));
1047 }
1048
1049 /*******************************************************************
1050  api_samr_chgpasswd_user
1051  ********************************************************************/
1052 static void api_samr_chgpasswd_user( uint16 vuid, prs_struct *data, prs_struct *rdata)
1053 {
1054         SAMR_Q_CHGPASSWD_USER q_u;
1055
1056         /* unknown 38 command */
1057         samr_io_q_chgpasswd_user("", &q_u, data, 0);
1058
1059         /* construct reply. */
1060         samr_reply_chgpasswd_user(&q_u, rdata);
1061 }
1062
1063
1064 /*******************************************************************
1065  samr_reply_unknown_38
1066  ********************************************************************/
1067 static void samr_reply_unknown_38(SAMR_Q_UNKNOWN_38 *q_u,
1068                                 prs_struct *rdata)
1069 {
1070         SAMR_R_UNKNOWN_38 r_u;
1071
1072         DEBUG(5,("samr_unknown_38: %d\n", __LINE__));
1073
1074         make_samr_r_unknown_38(&r_u);
1075
1076         /* store the response in the SMB stream */
1077         samr_io_r_unknown_38("", &r_u, rdata, 0);
1078
1079         DEBUG(5,("samr_unknown_38: %d\n", __LINE__));
1080 }
1081
1082 /*******************************************************************
1083  api_samr_unknown_38
1084  ********************************************************************/
1085 static void api_samr_unknown_38( uint16 vuid, prs_struct *data, prs_struct *rdata)
1086 {
1087         SAMR_Q_UNKNOWN_38 q_u;
1088
1089         /* unknown 38 command */
1090         samr_io_q_unknown_38("", &q_u, data, 0);
1091
1092         /* construct reply.  always indicate success */
1093         samr_reply_unknown_38(&q_u, rdata);
1094 }
1095
1096
1097 /*******************************************************************
1098  samr_reply_unknown_12
1099  ********************************************************************/
1100 static void samr_reply_unknown_12(SAMR_Q_UNKNOWN_12 *q_u,
1101                                 prs_struct *rdata)
1102 {
1103         fstring group_names[MAX_SAM_ENTRIES];
1104         uint8   group_attrs[MAX_SAM_ENTRIES];
1105         uint32 status     = 0;
1106         int num_gids = q_u->num_gids1;
1107         DOM_SID pol_sid;
1108
1109         SAMR_R_UNKNOWN_12 r_u;
1110
1111         DEBUG(5,("samr_unknown_12: %d\n", __LINE__));
1112
1113         /* find the policy handle.  open a policy on it. */
1114         if (status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->pol)) == -1))
1115         {
1116                 status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
1117         }
1118
1119         if (status == 0x0 && !get_lsa_policy_samr_sid(&q_u->pol, &pol_sid))
1120         {
1121                 status = NT_STATUS_OBJECT_TYPE_MISMATCH;
1122         }
1123
1124         if (status == 0x0)
1125         {
1126                 int i;
1127                 if (num_gids > MAX_SAM_ENTRIES)
1128                 {
1129                         num_gids = MAX_SAM_ENTRIES;
1130                         DEBUG(5,("samr_unknown_12: truncating entries to %d\n", num_gids));
1131                 }
1132
1133                 for (i = 0; i < num_gids && status == 0; i++)
1134                 {
1135                         DOM_SID sid;
1136                         sid_copy(&sid, &pol_sid);
1137                         sid_append_rid(&sid, q_u->gid[i]);
1138                         lookup_sid(&sid, group_names[i], &group_attrs[i]);
1139                         group_attrs[i] = 0x2;
1140                 }
1141         }
1142
1143         make_samr_r_unknown_12(&r_u, num_gids, group_names, group_attrs, status);
1144
1145         /* store the response in the SMB stream */
1146         samr_io_r_unknown_12("", &r_u, rdata, 0);
1147
1148         DEBUG(5,("samr_unknown_12: %d\n", __LINE__));
1149
1150 }
1151
1152 /*******************************************************************
1153  api_samr_unknown_12
1154  ********************************************************************/
1155 static void api_samr_unknown_12( uint16 vuid, prs_struct *data, prs_struct *rdata)
1156 {
1157         SAMR_Q_UNKNOWN_12 q_u;
1158
1159         /* grab the samr lookup names */
1160         samr_io_q_unknown_12("", &q_u, data, 0);
1161
1162         /* construct reply.  always indicate success */
1163         samr_reply_unknown_12(&q_u, rdata);
1164 }
1165
1166
1167 /*******************************************************************
1168  samr_reply_open_user
1169  ********************************************************************/
1170 static void samr_reply_open_user(SAMR_Q_OPEN_USER *q_u,
1171                                 prs_struct *rdata,
1172                                 int status)
1173 {
1174         SAMR_R_OPEN_USER r_u;
1175         struct sam_passwd *sam_pass;
1176         BOOL pol_open = False;
1177
1178         /* set up the SAMR open_user response */
1179         bzero(r_u.user_pol.data, POL_HND_SIZE);
1180
1181         r_u.status = 0x0;
1182
1183         /* find the policy handle.  open a policy on it. */
1184         if (r_u.status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->domain_pol)) == -1))
1185         {
1186                 r_u.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
1187         }
1188
1189         /* get a (unique) handle.  open a policy on it. */
1190         if (r_u.status == 0x0 && !(pol_open = open_lsa_policy_hnd(&(r_u.user_pol))))
1191         {
1192                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
1193         }
1194
1195         become_root(True);
1196         sam_pass = getsam21pwrid(q_u->user_rid);
1197         unbecome_root(True);
1198
1199         /* check that the RID exists in our domain. */
1200         if (r_u.status == 0x0 && sam_pass == NULL)
1201         {
1202                 r_u.status = 0xC0000000 | NT_STATUS_NO_SUCH_USER;
1203         }
1204
1205         /* associate the RID with the (unique) handle. */
1206         if (r_u.status == 0x0 && !set_lsa_policy_samr_rid(&(r_u.user_pol), q_u->user_rid))
1207         {
1208                 /* oh, whoops.  don't know what error message to return, here */
1209                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
1210         }
1211
1212         if (r_u.status != 0 && pol_open)
1213         {
1214                 close_lsa_policy_hnd(&(r_u.user_pol));
1215         }
1216
1217         DEBUG(5,("samr_open_user: %d\n", __LINE__));
1218
1219         /* store the response in the SMB stream */
1220         samr_io_r_open_user("", &r_u, rdata, 0);
1221
1222         DEBUG(5,("samr_open_user: %d\n", __LINE__));
1223
1224 }
1225
1226 /*******************************************************************
1227  api_samr_open_user
1228  ********************************************************************/
1229 static void api_samr_open_user( uint16 vuid, prs_struct *data, prs_struct *rdata)
1230 {
1231         SAMR_Q_OPEN_USER q_u;
1232
1233         /* grab the samr unknown 22 */
1234         samr_io_q_open_user("", &q_u, data, 0);
1235
1236         /* construct reply.  always indicate success */
1237         samr_reply_open_user(&q_u, rdata, 0x0);
1238 }
1239
1240
1241 /*************************************************************************
1242  get_user_info_10
1243  *************************************************************************/
1244 static BOOL get_user_info_10(SAM_USER_INFO_10 *id10, uint32 user_rid)
1245 {
1246         struct sam_passwd *sam_pass;
1247
1248         become_root(True);
1249         sam_pass = getsam21pwrid(user_rid);
1250         unbecome_root(True);
1251
1252         if (sam_pass == NULL)
1253         {
1254                 DEBUG(4,("User 0x%x not found\n", user_rid));
1255                 return False;
1256         }
1257
1258         DEBUG(3,("User:[%s]\n", sam_pass->nt_name));
1259
1260         make_sam_user_info10(id10, sam_pass->acct_ctrl); 
1261
1262         return True;
1263 }
1264
1265 /*************************************************************************
1266  get_user_info_21
1267  *************************************************************************/
1268 static BOOL get_user_info_21(SAM_USER_INFO_21 *id21, uint32 user_rid)
1269 {
1270         struct sam_passwd *sam_pass;
1271         LOGON_HRS hrs;
1272         int i;
1273
1274         become_root(True);
1275         sam_pass = getsam21pwrid(user_rid);
1276         unbecome_root(True);
1277
1278         if (sam_pass == NULL)
1279         {
1280                 DEBUG(4,("User 0x%x not found\n", user_rid));
1281                 return False;
1282         }
1283
1284         DEBUG(3,("User:[%s]\n", sam_pass->nt_name));
1285
1286         /* create a LOGON_HRS structure */
1287         hrs.len = sam_pass->hours_len;
1288         SMB_ASSERT_ARRAY(hrs.hours, hrs.len);
1289         for (i = 0; i < hrs.len; i++)
1290         {
1291                 hrs.hours[i] = sam_pass->hours[i];
1292         }
1293
1294         make_sam_user_info21(id21,
1295
1296                            &sam_pass->logon_time,
1297                            &sam_pass->logoff_time,
1298                            &sam_pass->kickoff_time,
1299                            &sam_pass->pass_last_set_time,
1300                            &sam_pass->pass_can_change_time,
1301                            &sam_pass->pass_must_change_time,
1302
1303                            sam_pass->nt_name, /* user_name */
1304                            sam_pass->full_name, /* full_name */
1305                            sam_pass->home_dir, /* home_dir */
1306                            sam_pass->dir_drive, /* dir_drive */
1307                            sam_pass->logon_script, /* logon_script */
1308                            sam_pass->profile_path, /* profile_path */
1309                            sam_pass->acct_desc, /* description */
1310                            sam_pass->workstations, /* workstations user can log in from */
1311                            sam_pass->unknown_str, /* don't know, yet */
1312                            sam_pass->munged_dial, /* dialin info.  contains dialin path and tel no */
1313
1314                            sam_pass->user_rid, /* RID user_id */
1315                            sam_pass->group_rid, /* RID group_id */
1316                            sam_pass->acct_ctrl,
1317
1318                            sam_pass->unknown_3, /* unknown_3 */
1319                            sam_pass->logon_divs, /* divisions per week */
1320                            &hrs, /* logon hours */
1321                            sam_pass->unknown_5,
1322                            sam_pass->unknown_6);
1323
1324         return True;
1325 }
1326
1327 /*******************************************************************
1328  samr_reply_query_userinfo
1329  ********************************************************************/
1330 static void samr_reply_query_userinfo(SAMR_Q_QUERY_USERINFO *q_u,
1331                                 prs_struct *rdata)
1332 {
1333         SAMR_R_QUERY_USERINFO r_u;
1334 #if 0
1335         SAM_USER_INFO_11 id11;
1336 #endif
1337         SAM_USER_INFO_10 id10;
1338         SAM_USER_INFO_21 id21;
1339         void *info = NULL;
1340
1341         uint32 status = 0x0;
1342         uint32 rid = 0x0;
1343
1344         DEBUG(5,("samr_reply_query_userinfo: %d\n", __LINE__));
1345
1346         /* search for the handle */
1347         if (status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->pol)) == -1))
1348         {
1349                 status = NT_STATUS_INVALID_HANDLE;
1350         }
1351
1352         /* find the user's rid */
1353         if (status == 0x0 && (rid = get_lsa_policy_samr_rid(&(q_u->pol))) == 0xffffffff)
1354         {
1355                 status = NT_STATUS_OBJECT_TYPE_MISMATCH;
1356         }
1357
1358         DEBUG(5,("samr_reply_query_userinfo: rid:0x%x\n", rid));
1359
1360         /* ok!  user info levels (there are lots: see MSDEV help), off we go... */
1361         if (status == 0x0)
1362         {
1363                 switch (q_u->switch_value)
1364                 {
1365                         case 0x10:
1366                         {
1367                                 info = (void*)&id10;
1368                                 status = get_user_info_10(&id10, rid) ? 0 : NT_STATUS_NO_SUCH_USER;
1369                                 break;
1370                         }
1371 #if 0
1372 /* whoops - got this wrong.  i think.  or don't understand what's happening. */
1373                         case 0x11:
1374                         {
1375                                 NTTIME expire;
1376                                 info = (void*)&id11;
1377                                 
1378                                 expire.low  = 0xffffffff;
1379                                 expire.high = 0x7fffffff;
1380
1381                                 make_sam_user_info11(&id11, &expire, "BROOKFIELDS$", 0x03ef, 0x201, 0x0080);
1382
1383                                 break;
1384                         }
1385 #endif
1386                         case 21:
1387                         {
1388                                 info = (void*)&id21;
1389                                 status = get_user_info_21(&id21, rid) ? 0 : NT_STATUS_NO_SUCH_USER;
1390                                 break;
1391                         }
1392
1393                         default:
1394                         {
1395                                 status = NT_STATUS_INVALID_INFO_CLASS;
1396
1397                                 break;
1398                         }
1399                 }
1400         }
1401
1402         make_samr_r_query_userinfo(&r_u, q_u->switch_value, info, status);
1403
1404         /* store the response in the SMB stream */
1405         samr_io_r_query_userinfo("", &r_u, rdata, 0);
1406
1407         DEBUG(5,("samr_reply_query_userinfo: %d\n", __LINE__));
1408
1409 }
1410
1411 /*******************************************************************
1412  api_samr_query_userinfo
1413  ********************************************************************/
1414 static void api_samr_query_userinfo( uint16 vuid, prs_struct *data, prs_struct *rdata)
1415 {
1416         SAMR_Q_QUERY_USERINFO q_u;
1417
1418         /* grab the samr unknown 24 */
1419         samr_io_q_query_userinfo("", &q_u, data, 0);
1420
1421         /* construct reply.  always indicate success */
1422         samr_reply_query_userinfo(&q_u, rdata);
1423 }
1424
1425
1426 /*******************************************************************
1427  samr_reply_query_usergroups
1428  ********************************************************************/
1429 static void samr_reply_query_usergroups(SAMR_Q_QUERY_USERGROUPS *q_u,
1430                                 prs_struct *rdata)
1431 {
1432         SAMR_R_QUERY_USERGROUPS r_u;
1433         uint32 status = 0x0;
1434
1435         struct sam_passwd *sam_pass;
1436         DOM_GID *gids = NULL;
1437         int num_groups = 0;
1438         uint32 rid;
1439
1440         DEBUG(5,("samr_query_usergroups: %d\n", __LINE__));
1441
1442         /* find the policy handle.  open a policy on it. */
1443         if (status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->pol)) == -1))
1444         {
1445                 status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
1446         }
1447
1448         /* find the user's rid */
1449         if (status == 0x0 && (rid = get_lsa_policy_samr_rid(&(q_u->pol))) == 0xffffffff)
1450         {
1451                 status = NT_STATUS_OBJECT_TYPE_MISMATCH;
1452         }
1453
1454         if (status == 0x0)
1455         {
1456                 become_root(True);
1457                 sam_pass = getsam21pwrid(rid);
1458                 unbecome_root(True);
1459
1460                 if (sam_pass == NULL)
1461                 {
1462                         status = 0xC0000000 | NT_STATUS_NO_SUCH_USER;
1463                 }
1464         }
1465
1466         if (status == 0x0)
1467         {
1468                 DOMAIN_GRP *mem_grp = NULL;
1469
1470                 become_root(True);
1471                 getusergroupsntnam(sam_pass->nt_name, &mem_grp, &num_groups);
1472                 unbecome_root(True);
1473
1474                 gids = NULL;
1475                 num_groups = make_dom_gids(mem_grp, num_groups, &gids);
1476
1477                 if (mem_grp != NULL)
1478                 {
1479                         free(mem_grp);
1480                 }
1481         }
1482
1483         /* construct the response.  lkclXXXX: gids are not copied! */
1484         make_samr_r_query_usergroups(&r_u, num_groups, gids, status);
1485
1486         /* store the response in the SMB stream */
1487         samr_io_r_query_usergroups("", &r_u, rdata, 0);
1488
1489         if (gids)
1490         {
1491                 free((char *)gids);
1492         }
1493
1494         DEBUG(5,("samr_query_usergroups: %d\n", __LINE__));
1495
1496 }
1497
1498 /*******************************************************************
1499  api_samr_query_usergroups
1500  ********************************************************************/
1501 static void api_samr_query_usergroups( uint16 vuid, prs_struct *data, prs_struct *rdata)
1502 {
1503         SAMR_Q_QUERY_USERGROUPS q_u;
1504         /* grab the samr unknown 32 */
1505         samr_io_q_query_usergroups("", &q_u, data, 0);
1506
1507         /* construct reply. */
1508         samr_reply_query_usergroups(&q_u, rdata);
1509 }
1510
1511
1512 /*******************************************************************
1513  samr_reply_query_dom_info
1514  ********************************************************************/
1515 static void samr_reply_query_dom_info(SAMR_Q_QUERY_DOMAIN_INFO *q_u,
1516                                 prs_struct *rdata)
1517 {
1518         SAMR_R_QUERY_DOMAIN_INFO r_u;
1519         SAM_UNK_CTR ctr;
1520         uint16 switch_value = 0x0;
1521         uint32 status = 0x0;
1522
1523         ZERO_STRUCT(r_u);
1524         ZERO_STRUCT(ctr);
1525
1526         r_u.ctr = &ctr;
1527
1528         DEBUG(5,("samr_reply_query_dom_info: %d\n", __LINE__));
1529
1530         /* find the policy handle.  open a policy on it. */
1531         if (r_u.status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->domain_pol)) == -1))
1532         {
1533                 r_u.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
1534                 DEBUG(5,("samr_reply_query_dom_info: invalid handle\n"));
1535         }
1536
1537         if (status == 0x0)
1538         {
1539                 switch (q_u->switch_value)
1540                 {
1541                         case 0x02:
1542                         {
1543                                 switch_value = 0x2;
1544                                 make_unk_info2(&ctr.info.inf2, global_sam_name, global_myname);
1545
1546                                 break;
1547                         }
1548                         default:
1549                         {
1550                                 status = 0xC0000000 | NT_STATUS_INVALID_INFO_CLASS;
1551                                 break;
1552                         }
1553                 }
1554         }
1555
1556         make_samr_r_query_dom_info(&r_u, switch_value, &ctr, status);
1557
1558         /* store the response in the SMB stream */
1559         samr_io_r_query_dom_info("", &r_u, rdata, 0);
1560
1561         DEBUG(5,("samr_query_dom_info: %d\n", __LINE__));
1562
1563 }
1564
1565 /*******************************************************************
1566  api_samr_query_dom_info
1567  ********************************************************************/
1568 static void api_samr_query_dom_info( uint16 vuid, prs_struct *data, prs_struct *rdata)
1569 {
1570         SAMR_Q_QUERY_DOMAIN_INFO q_e;
1571
1572         /* grab the samr unknown 8 command */
1573         samr_io_q_query_dom_info("", &q_e, data, 0);
1574
1575         /* construct reply. */
1576         samr_reply_query_dom_info(&q_e, rdata);
1577 }
1578
1579
1580
1581 /*******************************************************************
1582  samr_reply_unknown_32
1583  ********************************************************************/
1584 static void samr_reply_unknown_32(SAMR_Q_UNKNOWN_32 *q_u,
1585                                 prs_struct *rdata,
1586                                 int status)
1587 {
1588         int i;
1589         SAMR_R_UNKNOWN_32 r_u;
1590
1591         /* set up the SAMR unknown_32 response */
1592         bzero(r_u.pol.data, POL_HND_SIZE);
1593         if (status == 0)
1594         {
1595                 for (i = 4; i < POL_HND_SIZE; i++)
1596                 {
1597                         r_u.pol.data[i] = i+1;
1598                 }
1599         }
1600
1601         make_dom_rid4(&(r_u.rid4), 0x0030, 0, 0);
1602         r_u.status    = status;
1603
1604         DEBUG(5,("samr_unknown_32: %d\n", __LINE__));
1605
1606         /* store the response in the SMB stream */
1607         samr_io_r_unknown_32("", &r_u, rdata, 0);
1608
1609         DEBUG(5,("samr_unknown_32: %d\n", __LINE__));
1610
1611 }
1612
1613 /*******************************************************************
1614  api_samr_unknown_32
1615  ********************************************************************/
1616 static void api_samr_unknown_32( uint16 vuid, prs_struct *data, prs_struct *rdata)
1617 {
1618         uint32 status = 0;
1619         struct sam_passwd *sam_pass;
1620         fstring mach_acct;
1621
1622         SAMR_Q_UNKNOWN_32 q_u;
1623
1624         /* grab the samr unknown 32 */
1625         samr_io_q_unknown_32("", &q_u, data, 0);
1626
1627         /* find the machine account: tell the caller if it exists.
1628            lkclXXXX i have *no* idea if this is a problem or not
1629            or even if you are supposed to construct a different
1630            reply if the account already exists...
1631          */
1632
1633         fstrcpy(mach_acct, unistrn2(q_u.uni_mach_acct.buffer,
1634                                     q_u.uni_mach_acct.uni_str_len));
1635
1636         become_root(True);
1637         sam_pass = getsam21pwntnam(mach_acct);
1638         unbecome_root(True);
1639
1640         if (sam_pass != NULL)
1641         {
1642                 /* machine account exists: say so */
1643                 status = 0xC0000000 | NT_STATUS_USER_EXISTS;
1644         }
1645         else
1646         {
1647                 /* this could cause trouble... */
1648                 DEBUG(0,("trouble!\n"));
1649                 status = 0;
1650         }
1651
1652         /* construct reply. */
1653         samr_reply_unknown_32(&q_u, rdata, status);
1654 }
1655
1656
1657 /*******************************************************************
1658  samr_reply_connect_anon
1659  ********************************************************************/
1660 static void samr_reply_connect_anon(SAMR_Q_CONNECT_ANON *q_u,
1661                                 prs_struct *rdata)
1662 {
1663         SAMR_R_CONNECT_ANON r_u;
1664         BOOL pol_open = False;
1665
1666         /* set up the SAMR connect_anon response */
1667
1668         r_u.status = 0x0;
1669         /* get a (unique) handle.  open a policy on it. */
1670         if (r_u.status == 0x0 && !(pol_open = open_lsa_policy_hnd(&(r_u.connect_pol))))
1671         {
1672                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
1673         }
1674
1675         /* associate the domain SID with the (unique) handle. */
1676         if (r_u.status == 0x0 && !set_lsa_policy_samr_pol_status(&(r_u.connect_pol), q_u->unknown_0))
1677         {
1678                 /* oh, whoops.  don't know what error message to return, here */
1679                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
1680         }
1681
1682         if (r_u.status != 0 && pol_open)
1683         {
1684                 close_lsa_policy_hnd(&(r_u.connect_pol));
1685         }
1686
1687         DEBUG(5,("samr_connect_anon: %d\n", __LINE__));
1688
1689         /* store the response in the SMB stream */
1690         samr_io_r_connect_anon("", &r_u, rdata, 0);
1691
1692         DEBUG(5,("samr_connect_anon: %d\n", __LINE__));
1693
1694 }
1695
1696 /*******************************************************************
1697  api_samr_connect_anon
1698  ********************************************************************/
1699 static void api_samr_connect_anon( uint16 vuid, prs_struct *data, prs_struct *rdata)
1700 {
1701         SAMR_Q_CONNECT_ANON q_u;
1702
1703         /* grab the samr open policy */
1704         samr_io_q_connect_anon("", &q_u, data, 0);
1705
1706         /* construct reply.  always indicate success */
1707         samr_reply_connect_anon(&q_u, rdata);
1708 }
1709
1710 /*******************************************************************
1711  samr_reply_connect
1712  ********************************************************************/
1713 static void samr_reply_connect(SAMR_Q_CONNECT *q_u,
1714                                 prs_struct *rdata)
1715 {
1716         SAMR_R_CONNECT r_u;
1717         BOOL pol_open = False;
1718
1719         /* set up the SAMR connect response */
1720
1721         r_u.status = 0x0;
1722         /* get a (unique) handle.  open a policy on it. */
1723         if (r_u.status == 0x0 && !(pol_open = open_lsa_policy_hnd(&(r_u.connect_pol))))
1724         {
1725                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
1726         }
1727
1728         /* associate the domain SID with the (unique) handle. */
1729         if (r_u.status == 0x0 && !set_lsa_policy_samr_pol_status(&(r_u.connect_pol), q_u->unknown_0))
1730         {
1731                 /* oh, whoops.  don't know what error message to return, here */
1732                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
1733         }
1734
1735         if (r_u.status != 0 && pol_open)
1736         {
1737                 close_lsa_policy_hnd(&(r_u.connect_pol));
1738         }
1739
1740         DEBUG(5,("samr_connect: %d\n", __LINE__));
1741
1742         /* store the response in the SMB stream */
1743         samr_io_r_connect("", &r_u, rdata, 0);
1744
1745         DEBUG(5,("samr_connect: %d\n", __LINE__));
1746
1747 }
1748
1749 /*******************************************************************
1750  api_samr_connect
1751  ********************************************************************/
1752 static void api_samr_connect( uint16 vuid, prs_struct *data, prs_struct *rdata)
1753 {
1754         SAMR_Q_CONNECT q_u;
1755
1756         /* grab the samr open policy */
1757         samr_io_q_connect("", &q_u, data, 0);
1758
1759         /* construct reply.  always indicate success */
1760         samr_reply_connect(&q_u, rdata);
1761 }
1762
1763 /*******************************************************************
1764  samr_reply_open_alias
1765  ********************************************************************/
1766 static void samr_reply_open_alias(SAMR_Q_OPEN_ALIAS *q_u,
1767                                 prs_struct *rdata)
1768 {
1769         SAMR_R_OPEN_ALIAS r_u;
1770         DOM_SID sid;
1771         BOOL pol_open = False;
1772
1773         /* set up the SAMR open_alias response */
1774
1775         r_u.status = 0x0;
1776         /* get a (unique) handle.  open a policy on it. */
1777         if (r_u.status == 0x0 && !(pol_open = open_lsa_policy_hnd(&(r_u.pol))))
1778         {
1779                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
1780         }
1781
1782         /* associate a RID with the (unique) handle. */
1783         if (r_u.status == 0x0 && !set_lsa_policy_samr_rid(&(r_u.pol), q_u->rid_alias))
1784         {
1785                 /* oh, whoops.  don't know what error message to return, here */
1786                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
1787         }
1788
1789         sid_copy(&sid, &global_sid_S_1_5_20);
1790         sid_append_rid(&sid, q_u->rid_alias);
1791
1792         /* associate an alias SID with the (unique) handle. */
1793         if (r_u.status == 0x0 && !set_lsa_policy_samr_sid(&(r_u.pol), &sid))
1794         {
1795                 /* oh, whoops.  don't know what error message to return, here */
1796                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
1797         }
1798
1799         if (r_u.status != 0 && pol_open)
1800         {
1801                 close_lsa_policy_hnd(&(r_u.pol));
1802         }
1803
1804         DEBUG(5,("samr_open_alias: %d\n", __LINE__));
1805
1806         /* store the response in the SMB stream */
1807         samr_io_r_open_alias("", &r_u, rdata, 0);
1808
1809         DEBUG(5,("samr_open_alias: %d\n", __LINE__));
1810
1811 }
1812
1813 /*******************************************************************
1814  api_samr_open_alias
1815  ********************************************************************/
1816 static void api_samr_open_alias( uint16 vuid, prs_struct *data, prs_struct *rdata)
1817                                 
1818 {
1819         SAMR_Q_OPEN_ALIAS q_u;
1820
1821         /* grab the samr open policy */
1822         samr_io_q_open_alias("", &q_u, data, 0);
1823
1824         /* construct reply.  always indicate success */
1825         samr_reply_open_alias(&q_u, rdata);
1826 }
1827
1828 /*******************************************************************
1829  array of \PIPE\samr operations
1830  ********************************************************************/
1831 static struct api_struct api_samr_cmds [] =
1832 {
1833         { "SAMR_CLOSE_HND"        , SAMR_CLOSE_HND        , api_samr_close_hnd        },
1834         { "SAMR_CONNECT"          , SAMR_CONNECT          , api_samr_connect          },
1835         { "SAMR_CONNECT_ANON"     , SAMR_CONNECT_ANON     , api_samr_connect_anon     },
1836         { "SAMR_ENUM_DOM_USERS"   , SAMR_ENUM_DOM_USERS   , api_samr_enum_dom_users   },
1837         { "SAMR_ENUM_DOM_GROUPS"  , SAMR_ENUM_DOM_GROUPS  , api_samr_enum_dom_groups  },
1838         { "SAMR_ENUM_DOM_ALIASES" , SAMR_ENUM_DOM_ALIASES , api_samr_enum_dom_aliases },
1839         { "SAMR_QUERY_USERALIASES", SAMR_QUERY_USERALIASES, api_samr_query_useraliases},
1840         { "SAMR_QUERY_ALIASMEM"   , SAMR_QUERY_ALIASMEM   , api_samr_query_aliasmem   },
1841         { "SAMR_LOOKUP_NAMES"     , SAMR_LOOKUP_NAMES     , api_samr_lookup_names     },
1842         { "SAMR_OPEN_USER"        , SAMR_OPEN_USER        , api_samr_open_user        },
1843         { "SAMR_QUERY_USERINFO"   , SAMR_QUERY_USERINFO   , api_samr_query_userinfo   },
1844         { "SAMR_QUERY_DOMAIN_INFO", SAMR_QUERY_DOMAIN_INFO, api_samr_query_dom_info   },
1845         { "SAMR_QUERY_USERGROUPS" , SAMR_QUERY_USERGROUPS , api_samr_query_usergroups },
1846         { "SAMR_QUERY_DISPINFO"   , SAMR_QUERY_DISPINFO   , api_samr_query_dispinfo   },
1847         { "SAMR_QUERY_ALIASINFO"  , SAMR_QUERY_ALIASINFO  , api_samr_query_aliasinfo  },
1848         { "SAMR_0x32"             , 0x32                  , api_samr_unknown_32       },
1849         { "SAMR_UNKNOWN_12"       , SAMR_UNKNOWN_12       , api_samr_unknown_12       },
1850         { "SAMR_UNKNOWN_38"       , SAMR_UNKNOWN_38       , api_samr_unknown_38       },
1851         { "SAMR_CHGPASSWD_USER"   , SAMR_CHGPASSWD_USER   , api_samr_chgpasswd_user   },
1852         { "SAMR_OPEN_ALIAS"       , SAMR_OPEN_ALIAS       , api_samr_open_alias       },
1853         { "SAMR_OPEN_DOMAIN"      , SAMR_OPEN_DOMAIN      , api_samr_open_domain      },
1854         { "SAMR_UNKNOWN_3"        , SAMR_UNKNOWN_3        , api_samr_unknown_3        },
1855         { "SAMR_UNKNOWN_2C"       , SAMR_UNKNOWN_2C       , api_samr_unknown_2c       },
1856         { NULL                    , 0                     , NULL                      }
1857 };
1858
1859 /*******************************************************************
1860  receives a samr pipe and responds.
1861  ********************************************************************/
1862 BOOL api_samr_rpc(pipes_struct *p, prs_struct *data)
1863 {
1864     return api_rpcTNP(p, "api_samr_rpc", api_samr_cmds, data);
1865 }
1866