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