7b970d27d240327f74672673c222197a694b78a8
[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                 got_grps = True;
448
449                 while (num_entries < MAX_SAM_ENTRIES && ((name = domain_group_rids[num_entries].name) != NULL))
450                 {
451                         DOMAIN_GRP tmp_grp;
452
453                         fstrcpy(tmp_grp.name   , name);
454                         fstrcpy(tmp_grp.comment, "");
455                         tmp_grp.rid = domain_group_rids[num_entries].rid;
456                         tmp_grp.attr = 0x7;
457
458                         if (!add_domain_group(&grps, &num_entries, &tmp_grp))
459                         {
460                                 r_e.status = 0xC0000000 | NT_STATUS_NO_MEMORY;
461                                 break;
462                         }
463                 }
464
465                 become_root(True);
466                 ret = enumdomgroups(&grps, &num_entries);
467                 unbecome_root(True);
468                 if (!ret)
469                 {
470                         r_e.status = 0xC0000000 | NT_STATUS_NO_MEMORY;
471                 }
472         }
473
474         if (r_e.status == 0 && got_grps)
475         {
476                 make_samr_r_enum_dom_groups(&r_e, q_u->start_idx, num_entries, grps, r_e.status);
477         }
478
479         /* store the response in the SMB stream */
480         samr_io_r_enum_dom_groups("", &r_e, rdata, 0);
481
482         if (grps != NULL)
483         {
484                 free(grps);
485         }
486
487         DEBUG(5,("samr_enum_dom_groups: %d\n", __LINE__));
488 }
489
490 /*******************************************************************
491  api_samr_enum_dom_groups
492  ********************************************************************/
493 static void api_samr_enum_dom_groups( uint16 vuid, prs_struct *data, prs_struct *rdata)
494 {
495         SAMR_Q_ENUM_DOM_GROUPS q_e;
496
497         /* grab the samr open */
498         samr_io_q_enum_dom_groups("", &q_e, data, 0);
499
500         /* construct reply. */
501         samr_reply_enum_dom_groups(&q_e, rdata);
502 }
503
504
505 /*******************************************************************
506  samr_reply_enum_dom_aliases
507  ********************************************************************/
508 static void samr_reply_enum_dom_aliases(SAMR_Q_ENUM_DOM_ALIASES *q_u,
509                                 prs_struct *rdata)
510 {
511         SAMR_R_ENUM_DOM_ALIASES r_e;
512         LOCAL_GRP *alss = NULL;
513         int num_entries = 0;
514         DOM_SID sid;
515         fstring sid_str;
516
517         r_e.status = 0x0;
518         r_e.num_entries = 0;
519
520         /* find the policy handle.  open a policy on it. */
521         if (r_e.status == 0x0 && !get_lsa_policy_samr_sid(&q_u->pol, &sid))
522         {
523                 r_e.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
524         }
525
526         sid_to_string(sid_str, &sid);
527
528         DEBUG(5,("samr_reply_enum_dom_aliases: sid %s\n", sid_str));
529
530         /* well-known aliases */
531         if (sid_equal(&sid, &global_sid_S_1_5_20))
532         {
533                 char *name;
534
535                 while ((name = builtin_alias_rids[num_entries].name) != NULL)
536                 {
537                         LOCAL_GRP tmp_als;
538
539                         fstrcpy(tmp_als.name   , name);
540                         fstrcpy(tmp_als.comment, "");
541                         tmp_als.rid = builtin_alias_rids[num_entries].rid;
542
543                         if (!add_domain_alias(&alss, &num_entries, &tmp_als))
544                         {
545                                 r_e.status = 0xC0000000 | NT_STATUS_NO_MEMORY;
546                                 break;
547                         }
548                 }
549         }
550         else if (sid_equal(&sid, &global_sam_sid))
551         {
552                 BOOL ret;
553                 /* local aliases */
554                 num_entries = 0;
555
556                 become_root(True);
557                 ret = enumdomaliases(&alss, &num_entries);
558                 unbecome_root(True);
559                 if (!ret)
560                 {
561                         r_e.status = 0xC0000000 | NT_STATUS_NO_MEMORY;
562                 }
563         }
564                 
565         if (r_e.status == 0x0)
566         {
567                 make_samr_r_enum_dom_aliases(&r_e, num_entries, alss, r_e.status);
568         }
569
570         /* store the response in the SMB stream */
571         samr_io_r_enum_dom_aliases("", &r_e, rdata, 0);
572
573         if (alss != NULL)
574         {
575                 free(alss);
576         }
577
578         DEBUG(5,("samr_enum_dom_aliases: %d\n", __LINE__));
579
580 }
581
582 /*******************************************************************
583  api_samr_enum_dom_aliases
584  ********************************************************************/
585 static void api_samr_enum_dom_aliases( uint16 vuid, prs_struct *data, prs_struct *rdata)
586 {
587         SAMR_Q_ENUM_DOM_ALIASES q_e;
588
589         /* grab the samr open */
590         samr_io_q_enum_dom_aliases("", &q_e, data, 0);
591
592         /* construct reply. */
593         samr_reply_enum_dom_aliases(&q_e, rdata);
594 }
595
596
597 /*******************************************************************
598  samr_reply_query_dispinfo
599  ********************************************************************/
600 static void samr_reply_query_dispinfo(SAMR_Q_QUERY_DISPINFO *q_u,
601                                 prs_struct *rdata)
602 {
603         SAMR_R_QUERY_DISPINFO r_e;
604         SAM_INFO_CTR ctr;
605         SAM_INFO_1 info1;
606         SAM_INFO_2 info2;
607         SAM_USER_INFO_21 pass[MAX_SAM_ENTRIES];
608         int num_entries = 0;
609         int total_entries = 0;
610         BOOL got_pwds;
611         uint16 switch_level = 0x0;
612
613         ZERO_STRUCT(r_e);
614
615         r_e.status = 0x0;
616
617         DEBUG(5,("samr_reply_query_dispinfo: %d\n", __LINE__));
618
619         /* find the policy handle.  open a policy on it. */
620         if (r_e.status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->pol)) == -1))
621         {
622                 r_e.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
623                 DEBUG(5,("samr_reply_query_dispinfo: invalid handle\n"));
624         }
625
626         if (r_e.status == 0x0)
627         {
628                 become_root(True);
629                 got_pwds = get_sampwd_entries(pass, q_u->start_idx, &total_entries, &num_entries, MAX_SAM_ENTRIES, 0);
630                 unbecome_root(True);
631
632                 switch (q_u->switch_level)
633                 {
634                         case 0x1:
635                         {
636                         
637                                 /* query disp info is for users */
638                                 switch_level = 0x1;
639                                 make_sam_info_1(&info1, ACB_NORMAL,
640                                         q_u->start_idx, num_entries, pass);
641
642                                 ctr.sam.info1 = &info1;
643
644                                 break;
645                         }
646                         case 0x2:
647                         {
648                                 /* query disp info is for servers */
649                                 switch_level = 0x2;
650                                 make_sam_info_2(&info2, ACB_WSTRUST,
651                                         q_u->start_idx, num_entries, pass);
652
653                                 ctr.sam.info2 = &info2;
654
655                                 break;
656                         }
657                 }
658         }
659
660         if (r_e.status == 0 && got_pwds)
661         {
662                 make_samr_r_query_dispinfo(&r_e, switch_level, &ctr, r_e.status);
663         }
664
665         /* store the response in the SMB stream */
666         samr_io_r_query_dispinfo("", &r_e, rdata, 0);
667
668         DEBUG(5,("samr_query_dispinfo: %d\n", __LINE__));
669
670 }
671
672 /*******************************************************************
673  api_samr_query_dispinfo
674  ********************************************************************/
675 static void api_samr_query_dispinfo( uint16 vuid, prs_struct *data, prs_struct *rdata)
676 {
677         SAMR_Q_QUERY_DISPINFO q_e;
678
679         /* grab the samr open */
680         samr_io_q_query_dispinfo("", &q_e, data, 0);
681
682         /* construct reply. */
683         samr_reply_query_dispinfo(&q_e, rdata);
684 }
685
686
687 /*******************************************************************
688  samr_reply_query_aliasinfo
689  ********************************************************************/
690 static void samr_reply_query_aliasinfo(SAMR_Q_QUERY_ALIASINFO *q_u,
691                                 prs_struct *rdata)
692 {
693         SAMR_R_QUERY_ALIASINFO r_e;
694
695         r_e.status = 0x0;
696         r_e.ptr = 0;
697
698         /* find the policy handle.  open a policy on it. */
699         if (r_e.status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->pol)) == -1))
700         {
701                 r_e.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
702         }
703
704         DEBUG(5,("samr_reply_query_aliasinfo: %d\n", __LINE__));
705
706         if (r_e.status == 0x0)
707         {
708                 if (q_u->switch_level != 3)
709                 {
710                         r_e.status = NT_STATUS_INVALID_INFO_CLASS;
711                 }
712         }
713
714         make_samr_r_query_aliasinfo(&r_e, q_u->switch_level,
715                             "<account description>",
716                                 r_e.status);
717
718         /* store the response in the SMB stream */
719         samr_io_r_query_aliasinfo("", &r_e, rdata, 0);
720
721         DEBUG(5,("samr_query_aliasinfo: %d\n", __LINE__));
722
723 }
724
725 /*******************************************************************
726  api_samr_query_aliasinfo
727  ********************************************************************/
728 static void api_samr_query_aliasinfo( uint16 vuid, prs_struct *data, prs_struct *rdata)
729 {
730         SAMR_Q_QUERY_ALIASINFO q_e;
731
732         /* grab the samr open */
733         samr_io_q_query_aliasinfo("", &q_e, data, 0);
734
735         /* construct reply. */
736         samr_reply_query_aliasinfo(&q_e, rdata);
737 }
738
739
740 /*******************************************************************
741  samr_reply_lookup_ids
742  ********************************************************************/
743 static void samr_reply_lookup_ids(SAMR_Q_LOOKUP_IDS *q_u,
744                                 prs_struct *rdata)
745 {
746         uint32 rid[MAX_SAM_ENTRIES];
747         uint32 status     = 0;
748         int num_rids = 0;
749         int i;
750         struct sam_passwd *sam_pass;
751         DOM_SID usr_sid;
752         DOM_SID dom_sid;
753         uint32 user_rid;
754         fstring sam_sid_str;
755         fstring dom_sid_str;
756         fstring usr_sid_str;
757
758         SAMR_R_LOOKUP_IDS r_u;
759
760         DEBUG(5,("samr_lookup_ids: %d\n", __LINE__));
761
762         /* find the policy handle.  open a policy on it. */
763         if (status == 0x0 && !get_lsa_policy_samr_sid(&q_u->pol, &dom_sid))
764         {
765                 status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
766         }
767         else
768         {
769                 sid_to_string(dom_sid_str, &dom_sid       );
770                 sid_to_string(sam_sid_str, &global_sam_sid);
771         }
772
773         if (num_rids > MAX_SAM_ENTRIES)
774         {
775                 num_rids = MAX_SAM_ENTRIES;
776                 DEBUG(5,("samr_lookup_ids: truncating entries to %d\n", num_rids));
777         }
778
779         if (status == 0x0)
780         {
781                 usr_sid = q_u->sid[0].sid;
782                 sid_split_rid(&usr_sid, &user_rid);
783                 sid_to_string(usr_sid_str, &usr_sid);
784
785         }
786
787         if (status == 0x0)
788         {
789                 /* find the user account */
790                 become_root(True);
791                 sam_pass = getsam21pwrid(user_rid);
792                 unbecome_root(True);
793
794                 if (sam_pass == NULL)
795                 {
796                         status = 0xC0000000 | NT_STATUS_NO_SUCH_USER;
797                         num_rids = 0;
798                 }
799         }
800
801         if (status == 0x0)
802         {
803                 if (sid_equal(&dom_sid, &global_sid_S_1_5_20))
804                 {
805                         DEBUG(5,("lookup on S-1-5-20\n"));
806                 }
807                 else if (sid_equal(&dom_sid, &usr_sid))
808                 {
809                         DOMAIN_GRP *mem_grp = NULL;
810
811                         DEBUG(5,("lookup on Domain SID\n"));
812
813                         become_root(True);
814                         getusergroupsnam(sam_pass->smb_name, &mem_grp, &num_rids);
815                         unbecome_root(True);
816
817                         num_rids = MIN(num_rids, MAX_SAM_ENTRIES);
818
819                         if (mem_grp != NULL)
820                         {
821                                 for (i = 0; i < num_rids; i++)
822                                 {
823                                         rid[i] = mem_grp[i].rid;
824                                 }
825                                 free(mem_grp);
826                         }
827                 }
828                 else
829                 {
830                         status = 0xC0000000 | NT_STATUS_NO_SUCH_USER;
831                 }
832         }
833
834         make_samr_r_lookup_ids(&r_u, num_rids, rid, status);
835
836         /* store the response in the SMB stream */
837         samr_io_r_lookup_ids("", &r_u, rdata, 0);
838
839         DEBUG(5,("samr_lookup_ids: %d\n", __LINE__));
840
841 }
842
843 /*******************************************************************
844  api_samr_lookup_ids
845  ********************************************************************/
846 static void api_samr_lookup_ids( uint16 vuid, prs_struct *data, prs_struct *rdata)
847 {
848         SAMR_Q_LOOKUP_IDS q_u;
849
850         /* grab the samr 0x10 */
851         samr_io_q_lookup_ids("", &q_u, data, 0);
852
853         /* construct reply.  always indicate success */
854         samr_reply_lookup_ids(&q_u, rdata);
855 }
856
857 /*******************************************************************
858  samr_reply_lookup_names
859  ********************************************************************/
860 static void samr_reply_lookup_names(SAMR_Q_LOOKUP_NAMES *q_u,
861                                 prs_struct *rdata)
862 {
863         uint32 rid [MAX_SAM_ENTRIES];
864         uint8  type[MAX_SAM_ENTRIES];
865         uint32 status     = 0;
866         int i;
867         int num_rids = q_u->num_rids1;
868
869         SAMR_R_LOOKUP_NAMES r_u;
870
871         DEBUG(5,("samr_lookup_names: %d\n", __LINE__));
872
873         if (num_rids > MAX_SAM_ENTRIES)
874         {
875                 num_rids = MAX_SAM_ENTRIES;
876                 DEBUG(5,("samr_lookup_names: truncating entries to %d\n", num_rids));
877         }
878
879         SMB_ASSERT_ARRAY(q_u->uni_user_name, num_rids);
880
881         for (i = 0; i < num_rids && status == 0; i++)
882         {
883                 fstring name;
884                 fstrcpy(name, unistrn2(q_u->uni_user_name[i].buffer, q_u->uni_user_name[i].uni_str_len));
885
886                 status = lookup_rid(name, &(rid[i]), &(type[i]));
887         }
888
889         make_samr_r_lookup_names(&r_u, num_rids, rid, type, status);
890
891         /* store the response in the SMB stream */
892         samr_io_r_lookup_names("", &r_u, rdata, 0);
893
894         DEBUG(5,("samr_lookup_names: %d\n", __LINE__));
895
896 }
897
898 /*******************************************************************
899  api_samr_lookup_names
900  ********************************************************************/
901 static void api_samr_lookup_names( uint16 vuid, prs_struct *data, prs_struct *rdata)
902 {
903         SAMR_Q_LOOKUP_NAMES q_u;
904
905         /* grab the samr lookup names */
906         samr_io_q_lookup_names("", &q_u, data, 0);
907
908         /* construct reply.  always indicate success */
909         samr_reply_lookup_names(&q_u, rdata);
910 }
911
912 /*******************************************************************
913  samr_reply_chgpasswd_user
914  ********************************************************************/
915 static void samr_reply_chgpasswd_user(SAMR_Q_CHGPASSWD_USER *q_u,
916                                 prs_struct *rdata)
917 {
918         SAMR_R_CHGPASSWD_USER r_u;
919         uint32 status = 0x0;
920         fstring user_name;
921         fstring wks;
922
923         fstrcpy(user_name, unistrn2(q_u->uni_user_name.buffer, q_u->uni_user_name.uni_str_len));
924         fstrcpy(wks      , unistrn2(q_u->uni_dest_host.buffer, q_u->uni_dest_host.uni_str_len));
925
926         DEBUG(5,("samr_chgpasswd_user: user: %s wks: %s\n", user_name, wks));
927
928         if (!pass_oem_change(user_name,
929                              q_u->lm_newpass.pass, q_u->lm_oldhash.hash,
930                              q_u->nt_newpass.pass, q_u->nt_oldhash.hash))
931         {
932                 status = 0xC0000000 | NT_STATUS_WRONG_PASSWORD;
933         }
934
935         make_samr_r_chgpasswd_user(&r_u, status);
936
937         /* store the response in the SMB stream */
938         samr_io_r_chgpasswd_user("", &r_u, rdata, 0);
939
940         DEBUG(5,("samr_chgpasswd_user: %d\n", __LINE__));
941 }
942
943 /*******************************************************************
944  api_samr_chgpasswd_user
945  ********************************************************************/
946 static void api_samr_chgpasswd_user( uint16 vuid, prs_struct *data, prs_struct *rdata)
947 {
948         SAMR_Q_CHGPASSWD_USER q_u;
949
950         /* unknown 38 command */
951         samr_io_q_chgpasswd_user("", &q_u, data, 0);
952
953         /* construct reply. */
954         samr_reply_chgpasswd_user(&q_u, rdata);
955 }
956
957
958 /*******************************************************************
959  samr_reply_unknown_38
960  ********************************************************************/
961 static void samr_reply_unknown_38(SAMR_Q_UNKNOWN_38 *q_u,
962                                 prs_struct *rdata)
963 {
964         SAMR_R_UNKNOWN_38 r_u;
965
966         DEBUG(5,("samr_unknown_38: %d\n", __LINE__));
967
968         make_samr_r_unknown_38(&r_u);
969
970         /* store the response in the SMB stream */
971         samr_io_r_unknown_38("", &r_u, rdata, 0);
972
973         DEBUG(5,("samr_unknown_38: %d\n", __LINE__));
974 }
975
976 /*******************************************************************
977  api_samr_unknown_38
978  ********************************************************************/
979 static void api_samr_unknown_38( uint16 vuid, prs_struct *data, prs_struct *rdata)
980 {
981         SAMR_Q_UNKNOWN_38 q_u;
982
983         /* unknown 38 command */
984         samr_io_q_unknown_38("", &q_u, data, 0);
985
986         /* construct reply.  always indicate success */
987         samr_reply_unknown_38(&q_u, rdata);
988 }
989
990
991 /*******************************************************************
992  samr_reply_unknown_12
993  ********************************************************************/
994 static void samr_reply_unknown_12(SAMR_Q_UNKNOWN_12 *q_u,
995                                 prs_struct *rdata)
996 {
997         fstring group_names[MAX_SAM_ENTRIES];
998         uint32  group_attrs[MAX_SAM_ENTRIES];
999         uint32 status     = 0;
1000         int num_gids = q_u->num_gids1;
1001
1002         SAMR_R_UNKNOWN_12 r_u;
1003
1004         DEBUG(5,("samr_unknown_12: %d\n", __LINE__));
1005
1006         /* find the policy handle.  open a policy on it. */
1007         if (status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->pol)) == -1))
1008         {
1009                 status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
1010         }
1011
1012         if (status == 0x0)
1013         {
1014                 int i;
1015                 if (num_gids > MAX_SAM_ENTRIES)
1016                 {
1017                         num_gids = MAX_SAM_ENTRIES;
1018                         DEBUG(5,("samr_unknown_12: truncating entries to %d\n", num_gids));
1019                 }
1020
1021                 for (i = 0; i < num_gids && status == 0; i++)
1022                 {
1023                         fstrcpy(group_names[i], "dummy group");
1024                         group_attrs[i] = 0x2;
1025                 }
1026         }
1027
1028         make_samr_r_unknown_12(&r_u, num_gids, group_names, group_attrs, status);
1029
1030         /* store the response in the SMB stream */
1031         samr_io_r_unknown_12("", &r_u, rdata, 0);
1032
1033         DEBUG(5,("samr_unknown_12: %d\n", __LINE__));
1034
1035 }
1036
1037 /*******************************************************************
1038  api_samr_unknown_12
1039  ********************************************************************/
1040 static void api_samr_unknown_12( uint16 vuid, prs_struct *data, prs_struct *rdata)
1041 {
1042         SAMR_Q_UNKNOWN_12 q_u;
1043
1044         /* grab the samr lookup names */
1045         samr_io_q_unknown_12("", &q_u, data, 0);
1046
1047         /* construct reply.  always indicate success */
1048         samr_reply_unknown_12(&q_u, rdata);
1049 }
1050
1051
1052 /*******************************************************************
1053  samr_reply_open_user
1054  ********************************************************************/
1055 static void samr_reply_open_user(SAMR_Q_OPEN_USER *q_u,
1056                                 prs_struct *rdata,
1057                                 int status)
1058 {
1059         SAMR_R_OPEN_USER r_u;
1060         struct sam_passwd *sam_pass;
1061         BOOL pol_open = False;
1062
1063         /* set up the SAMR open_user response */
1064         bzero(r_u.user_pol.data, POL_HND_SIZE);
1065
1066         r_u.status = 0x0;
1067
1068         /* find the policy handle.  open a policy on it. */
1069         if (r_u.status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->domain_pol)) == -1))
1070         {
1071                 r_u.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
1072         }
1073
1074         /* get a (unique) handle.  open a policy on it. */
1075         if (r_u.status == 0x0 && !(pol_open = open_lsa_policy_hnd(&(r_u.user_pol))))
1076         {
1077                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
1078         }
1079
1080         become_root(True);
1081         sam_pass = getsam21pwrid(q_u->user_rid);
1082         unbecome_root(True);
1083
1084         /* check that the RID exists in our domain. */
1085         if (r_u.status == 0x0 && sam_pass == NULL)
1086         {
1087                 r_u.status = 0xC0000000 | NT_STATUS_NO_SUCH_USER;
1088         }
1089
1090         /* associate the RID with the (unique) handle. */
1091         if (r_u.status == 0x0 && !set_lsa_policy_samr_rid(&(r_u.user_pol), q_u->user_rid))
1092         {
1093                 /* oh, whoops.  don't know what error message to return, here */
1094                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
1095         }
1096
1097         if (r_u.status != 0 && pol_open)
1098         {
1099                 close_lsa_policy_hnd(&(r_u.user_pol));
1100         }
1101
1102         DEBUG(5,("samr_open_user: %d\n", __LINE__));
1103
1104         /* store the response in the SMB stream */
1105         samr_io_r_open_user("", &r_u, rdata, 0);
1106
1107         DEBUG(5,("samr_open_user: %d\n", __LINE__));
1108
1109 }
1110
1111 /*******************************************************************
1112  api_samr_open_user
1113  ********************************************************************/
1114 static void api_samr_open_user( uint16 vuid, prs_struct *data, prs_struct *rdata)
1115 {
1116         SAMR_Q_OPEN_USER q_u;
1117
1118         /* grab the samr unknown 22 */
1119         samr_io_q_open_user("", &q_u, data, 0);
1120
1121         /* construct reply.  always indicate success */
1122         samr_reply_open_user(&q_u, rdata, 0x0);
1123 }
1124
1125
1126 /*************************************************************************
1127  get_user_info_10
1128  *************************************************************************/
1129 static BOOL get_user_info_10(SAM_USER_INFO_10 *id10, uint32 user_rid)
1130 {
1131         struct smb_passwd *smb_pass;
1132
1133         if (!pwdb_rid_is_user(user_rid))
1134         {
1135                 DEBUG(4,("RID 0x%x is not a user RID\n", user_rid));
1136                 return False;
1137         }
1138
1139         become_root(True);
1140         smb_pass = getsmbpwrid(user_rid);
1141         unbecome_root(True);
1142
1143         if (smb_pass == NULL)
1144         {
1145                 DEBUG(4,("User 0x%x not found\n", user_rid));
1146                 return False;
1147         }
1148
1149         DEBUG(3,("User:[%s]\n", smb_pass->smb_name));
1150
1151         make_sam_user_info10(id10, smb_pass->acct_ctrl); 
1152
1153         return True;
1154 }
1155
1156 /*************************************************************************
1157  get_user_info_21
1158  *************************************************************************/
1159 static BOOL get_user_info_21(SAM_USER_INFO_21 *id21, uint32 user_rid)
1160 {
1161         NTTIME dummy_time;
1162         struct sam_passwd *sam_pass;
1163         LOGON_HRS hrs;
1164         int i;
1165
1166         if (!pwdb_rid_is_user(user_rid))
1167         {
1168                 DEBUG(4,("RID 0x%x is not a user RID\n", user_rid));
1169                 return False;
1170         }
1171
1172         become_root(True);
1173         sam_pass = getsam21pwrid(user_rid);
1174         unbecome_root(True);
1175
1176         if (sam_pass == NULL)
1177         {
1178                 DEBUG(4,("User 0x%x not found\n", user_rid));
1179                 return False;
1180         }
1181
1182         DEBUG(3,("User:[%s]\n", sam_pass->smb_name));
1183
1184         dummy_time.low  = 0xffffffff;
1185         dummy_time.high = 0x7fffffff;
1186
1187         DEBUG(0,("get_user_info_21 - TODO: convert unix times to NTTIMEs\n"));
1188
1189         /* create a LOGON_HRS structure */
1190         hrs.len = sam_pass->hours_len;
1191         SMB_ASSERT_ARRAY(hrs.hours, hrs.len);
1192         for (i = 0; i < hrs.len; i++)
1193         {
1194                 hrs.hours[i] = sam_pass->hours[i];
1195         }
1196
1197         make_sam_user_info21(id21,
1198
1199                            &dummy_time, /* logon_time */
1200                            &dummy_time, /* logoff_time */
1201                            &dummy_time, /* kickoff_time */
1202                            &dummy_time, /* pass_last_set_time */
1203                            &dummy_time, /* pass_can_change_time */
1204                            &dummy_time, /* pass_must_change_time */
1205
1206                            sam_pass->smb_name, /* user_name */
1207                            sam_pass->full_name, /* full_name */
1208                            sam_pass->home_dir, /* home_dir */
1209                            sam_pass->dir_drive, /* dir_drive */
1210                            sam_pass->logon_script, /* logon_script */
1211                            sam_pass->profile_path, /* profile_path */
1212                            sam_pass->acct_desc, /* description */
1213                            sam_pass->workstations, /* workstations user can log in from */
1214                            sam_pass->unknown_str, /* don't know, yet */
1215                            sam_pass->munged_dial, /* dialin info.  contains dialin path and tel no */
1216
1217                            sam_pass->user_rid, /* RID user_id */
1218                            sam_pass->group_rid, /* RID group_id */
1219                        sam_pass->acct_ctrl,
1220
1221                    sam_pass->unknown_3, /* unknown_3 */
1222                        sam_pass->logon_divs, /* divisions per week */
1223                            &hrs, /* logon hours */
1224                        sam_pass->unknown_5,
1225                        sam_pass->unknown_6);
1226
1227         return True;
1228 }
1229
1230 /*******************************************************************
1231  samr_reply_query_userinfo
1232  ********************************************************************/
1233 static void samr_reply_query_userinfo(SAMR_Q_QUERY_USERINFO *q_u,
1234                                 prs_struct *rdata)
1235 {
1236         SAMR_R_QUERY_USERINFO r_u;
1237 #if 0
1238         SAM_USER_INFO_11 id11;
1239 #endif
1240         SAM_USER_INFO_10 id10;
1241         SAM_USER_INFO_21 id21;
1242         void *info = NULL;
1243
1244         uint32 status = 0x0;
1245         uint32 rid = 0x0;
1246
1247         DEBUG(5,("samr_reply_query_userinfo: %d\n", __LINE__));
1248
1249         /* search for the handle */
1250         if (status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->pol)) == -1))
1251         {
1252                 status = NT_STATUS_INVALID_HANDLE;
1253         }
1254
1255         /* find the user's rid */
1256         if (status == 0x0 && (rid = get_lsa_policy_samr_rid(&(q_u->pol))) == 0xffffffff)
1257         {
1258                 status = NT_STATUS_OBJECT_TYPE_MISMATCH;
1259         }
1260
1261         DEBUG(5,("samr_reply_query_userinfo: rid:0x%x\n", rid));
1262
1263         /* ok!  user info levels (there are lots: see MSDEV help), off we go... */
1264         if (status == 0x0)
1265         {
1266                 switch (q_u->switch_value)
1267                 {
1268                         case 0x10:
1269                         {
1270                                 info = (void*)&id10;
1271                                 status = get_user_info_10(&id10, rid) ? 0 : NT_STATUS_NO_SUCH_USER;
1272                                 break;
1273                         }
1274 #if 0
1275 /* whoops - got this wrong.  i think.  or don't understand what's happening. */
1276                         case 0x11:
1277                         {
1278                                 NTTIME expire;
1279                                 info = (void*)&id11;
1280                                 
1281                                 expire.low  = 0xffffffff;
1282                                 expire.high = 0x7fffffff;
1283
1284                                 make_sam_user_info11(&id11, &expire, "BROOKFIELDS$", 0x03ef, 0x201, 0x0080);
1285
1286                                 break;
1287                         }
1288 #endif
1289                         case 21:
1290                         {
1291                                 info = (void*)&id21;
1292                                 status = get_user_info_21(&id21, rid) ? 0 : NT_STATUS_NO_SUCH_USER;
1293                                 break;
1294                         }
1295
1296                         default:
1297                         {
1298                                 status = NT_STATUS_INVALID_INFO_CLASS;
1299
1300                                 break;
1301                         }
1302                 }
1303         }
1304
1305         make_samr_r_query_userinfo(&r_u, q_u->switch_value, info, status);
1306
1307         /* store the response in the SMB stream */
1308         samr_io_r_query_userinfo("", &r_u, rdata, 0);
1309
1310         DEBUG(5,("samr_reply_query_userinfo: %d\n", __LINE__));
1311
1312 }
1313
1314 /*******************************************************************
1315  api_samr_query_userinfo
1316  ********************************************************************/
1317 static void api_samr_query_userinfo( uint16 vuid, prs_struct *data, prs_struct *rdata)
1318 {
1319         SAMR_Q_QUERY_USERINFO q_u;
1320
1321         /* grab the samr unknown 24 */
1322         samr_io_q_query_userinfo("", &q_u, data, 0);
1323
1324         /* construct reply.  always indicate success */
1325         samr_reply_query_userinfo(&q_u, rdata);
1326 }
1327
1328
1329 /*******************************************************************
1330  samr_reply_query_usergroups
1331  ********************************************************************/
1332 static void samr_reply_query_usergroups(SAMR_Q_QUERY_USERGROUPS *q_u,
1333                                 prs_struct *rdata)
1334 {
1335         SAMR_R_QUERY_USERGROUPS r_u;
1336         uint32 status = 0x0;
1337
1338         struct sam_passwd *sam_pass;
1339         DOM_GID *gids = NULL;
1340         int num_groups = 0;
1341         uint32 rid;
1342
1343         DEBUG(5,("samr_query_usergroups: %d\n", __LINE__));
1344
1345         /* find the policy handle.  open a policy on it. */
1346         if (status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->pol)) == -1))
1347         {
1348                 status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
1349         }
1350
1351         /* find the user's rid */
1352         if (status == 0x0 && (rid = get_lsa_policy_samr_rid(&(q_u->pol))) == 0xffffffff)
1353         {
1354                 status = NT_STATUS_OBJECT_TYPE_MISMATCH;
1355         }
1356
1357         if (status == 0x0)
1358         {
1359                 become_root(True);
1360                 sam_pass = getsam21pwrid(rid);
1361                 unbecome_root(True);
1362
1363                 if (sam_pass == NULL)
1364                 {
1365                         status = 0xC0000000 | NT_STATUS_NO_SUCH_USER;
1366                 }
1367         }
1368
1369         if (status == 0x0)
1370         {
1371                 DOMAIN_GRP *mem_grp = NULL;
1372
1373                 become_root(True);
1374                 getusergroupsnam(sam_pass->smb_name, &mem_grp, &num_groups);
1375                 unbecome_root(True);
1376
1377                 gids = NULL;
1378                 num_groups = make_dom_gids(mem_grp, num_groups, &gids);
1379
1380                 if (mem_grp != NULL)
1381                 {
1382                         free(mem_grp);
1383                 }
1384         }
1385
1386         /* construct the response.  lkclXXXX: gids are not copied! */
1387         make_samr_r_query_usergroups(&r_u, num_groups, gids, status);
1388
1389         /* store the response in the SMB stream */
1390         samr_io_r_query_usergroups("", &r_u, rdata, 0);
1391
1392         if (gids)
1393         {
1394                 free((char *)gids);
1395         }
1396
1397         DEBUG(5,("samr_query_usergroups: %d\n", __LINE__));
1398
1399 }
1400
1401 /*******************************************************************
1402  api_samr_query_usergroups
1403  ********************************************************************/
1404 static void api_samr_query_usergroups( uint16 vuid, prs_struct *data, prs_struct *rdata)
1405 {
1406         SAMR_Q_QUERY_USERGROUPS q_u;
1407         /* grab the samr unknown 32 */
1408         samr_io_q_query_usergroups("", &q_u, data, 0);
1409
1410         /* construct reply. */
1411         samr_reply_query_usergroups(&q_u, rdata);
1412 }
1413
1414
1415 /*******************************************************************
1416  samr_reply_query_dom_info
1417  ********************************************************************/
1418 static void samr_reply_query_dom_info(SAMR_Q_QUERY_DOMAIN_INFO *q_u,
1419                                 prs_struct *rdata)
1420 {
1421         SAMR_R_QUERY_DOMAIN_INFO r_u;
1422         SAM_UNK_CTR ctr;
1423         uint16 switch_value = 0x0;
1424         uint32 status = 0x0;
1425
1426         ZERO_STRUCT(r_u);
1427         ZERO_STRUCT(ctr);
1428
1429         r_u.ctr = &ctr;
1430
1431         DEBUG(5,("samr_reply_query_dom_info: %d\n", __LINE__));
1432
1433         /* find the policy handle.  open a policy on it. */
1434         if (r_u.status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->domain_pol)) == -1))
1435         {
1436                 r_u.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
1437                 DEBUG(5,("samr_reply_query_dom_info: invalid handle\n"));
1438         }
1439
1440         if (status == 0x0)
1441         {
1442                 switch (q_u->switch_value)
1443                 {
1444                         case 0x02:
1445                         {
1446                                 switch_value = 0x2;
1447                                 make_unk_info2(&ctr.info.inf2, global_sam_name, global_myname);
1448
1449                                 break;
1450                         }
1451                         default:
1452                         {
1453                                 status = 0xC0000000 | NT_STATUS_INVALID_INFO_CLASS;
1454                                 break;
1455                         }
1456                 }
1457         }
1458
1459         make_samr_r_query_dom_info(&r_u, switch_value, &ctr, status);
1460
1461         /* store the response in the SMB stream */
1462         samr_io_r_query_dom_info("", &r_u, rdata, 0);
1463
1464         DEBUG(5,("samr_query_dom_info: %d\n", __LINE__));
1465
1466 }
1467
1468 /*******************************************************************
1469  api_samr_query_dom_info
1470  ********************************************************************/
1471 static void api_samr_query_dom_info( uint16 vuid, prs_struct *data, prs_struct *rdata)
1472 {
1473         SAMR_Q_QUERY_DOMAIN_INFO q_e;
1474
1475         /* grab the samr unknown 8 command */
1476         samr_io_q_query_dom_info("", &q_e, data, 0);
1477
1478         /* construct reply. */
1479         samr_reply_query_dom_info(&q_e, rdata);
1480 }
1481
1482
1483
1484 /*******************************************************************
1485  samr_reply_unknown_32
1486  ********************************************************************/
1487 static void samr_reply_unknown_32(SAMR_Q_UNKNOWN_32 *q_u,
1488                                 prs_struct *rdata,
1489                                 int status)
1490 {
1491         int i;
1492         SAMR_R_UNKNOWN_32 r_u;
1493
1494         /* set up the SAMR unknown_32 response */
1495         bzero(r_u.pol.data, POL_HND_SIZE);
1496         if (status == 0)
1497         {
1498                 for (i = 4; i < POL_HND_SIZE; i++)
1499                 {
1500                         r_u.pol.data[i] = i+1;
1501                 }
1502         }
1503
1504         make_dom_rid4(&(r_u.rid4), 0x0030, 0, 0);
1505         r_u.status    = status;
1506
1507         DEBUG(5,("samr_unknown_32: %d\n", __LINE__));
1508
1509         /* store the response in the SMB stream */
1510         samr_io_r_unknown_32("", &r_u, rdata, 0);
1511
1512         DEBUG(5,("samr_unknown_32: %d\n", __LINE__));
1513
1514 }
1515
1516 /*******************************************************************
1517  api_samr_unknown_32
1518  ********************************************************************/
1519 static void api_samr_unknown_32( uint16 vuid, prs_struct *data, prs_struct *rdata)
1520 {
1521         uint32 status = 0;
1522         struct sam_passwd *sam_pass;
1523         fstring mach_acct;
1524
1525         SAMR_Q_UNKNOWN_32 q_u;
1526
1527         /* grab the samr unknown 32 */
1528         samr_io_q_unknown_32("", &q_u, data, 0);
1529
1530         /* find the machine account: tell the caller if it exists.
1531            lkclXXXX i have *no* idea if this is a problem or not
1532            or even if you are supposed to construct a different
1533            reply if the account already exists...
1534          */
1535
1536         fstrcpy(mach_acct, unistrn2(q_u.uni_mach_acct.buffer,
1537                                     q_u.uni_mach_acct.uni_str_len));
1538
1539         become_root(True);
1540         sam_pass = getsam21pwnam(mach_acct);
1541         unbecome_root(True);
1542
1543         if (sam_pass != NULL)
1544         {
1545                 /* machine account exists: say so */
1546                 status = 0xC0000000 | NT_STATUS_USER_EXISTS;
1547         }
1548         else
1549         {
1550                 /* this could cause trouble... */
1551                 DEBUG(0,("trouble!\n"));
1552                 status = 0;
1553         }
1554
1555         /* construct reply. */
1556         samr_reply_unknown_32(&q_u, rdata, status);
1557 }
1558
1559
1560 /*******************************************************************
1561  samr_reply_connect_anon
1562  ********************************************************************/
1563 static void samr_reply_connect_anon(SAMR_Q_CONNECT_ANON *q_u,
1564                                 prs_struct *rdata)
1565 {
1566         SAMR_R_CONNECT_ANON r_u;
1567         BOOL pol_open = False;
1568
1569         /* set up the SAMR connect_anon response */
1570
1571         r_u.status = 0x0;
1572         /* get a (unique) handle.  open a policy on it. */
1573         if (r_u.status == 0x0 && !(pol_open = open_lsa_policy_hnd(&(r_u.connect_pol))))
1574         {
1575                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
1576         }
1577
1578         /* associate the domain SID with the (unique) handle. */
1579         if (r_u.status == 0x0 && !set_lsa_policy_samr_pol_status(&(r_u.connect_pol), q_u->unknown_0))
1580         {
1581                 /* oh, whoops.  don't know what error message to return, here */
1582                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
1583         }
1584
1585         if (r_u.status != 0 && pol_open)
1586         {
1587                 close_lsa_policy_hnd(&(r_u.connect_pol));
1588         }
1589
1590         DEBUG(5,("samr_connect_anon: %d\n", __LINE__));
1591
1592         /* store the response in the SMB stream */
1593         samr_io_r_connect_anon("", &r_u, rdata, 0);
1594
1595         DEBUG(5,("samr_connect_anon: %d\n", __LINE__));
1596
1597 }
1598
1599 /*******************************************************************
1600  api_samr_connect_anon
1601  ********************************************************************/
1602 static void api_samr_connect_anon( uint16 vuid, prs_struct *data, prs_struct *rdata)
1603 {
1604         SAMR_Q_CONNECT_ANON q_u;
1605
1606         /* grab the samr open policy */
1607         samr_io_q_connect_anon("", &q_u, data, 0);
1608
1609         /* construct reply.  always indicate success */
1610         samr_reply_connect_anon(&q_u, rdata);
1611 }
1612
1613 /*******************************************************************
1614  samr_reply_connect
1615  ********************************************************************/
1616 static void samr_reply_connect(SAMR_Q_CONNECT *q_u,
1617                                 prs_struct *rdata)
1618 {
1619         SAMR_R_CONNECT r_u;
1620         BOOL pol_open = False;
1621
1622         /* set up the SAMR connect response */
1623
1624         r_u.status = 0x0;
1625         /* get a (unique) handle.  open a policy on it. */
1626         if (r_u.status == 0x0 && !(pol_open = open_lsa_policy_hnd(&(r_u.connect_pol))))
1627         {
1628                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
1629         }
1630
1631         /* associate the domain SID with the (unique) handle. */
1632         if (r_u.status == 0x0 && !set_lsa_policy_samr_pol_status(&(r_u.connect_pol), q_u->unknown_0))
1633         {
1634                 /* oh, whoops.  don't know what error message to return, here */
1635                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
1636         }
1637
1638         if (r_u.status != 0 && pol_open)
1639         {
1640                 close_lsa_policy_hnd(&(r_u.connect_pol));
1641         }
1642
1643         DEBUG(5,("samr_connect: %d\n", __LINE__));
1644
1645         /* store the response in the SMB stream */
1646         samr_io_r_connect("", &r_u, rdata, 0);
1647
1648         DEBUG(5,("samr_connect: %d\n", __LINE__));
1649
1650 }
1651
1652 /*******************************************************************
1653  api_samr_connect
1654  ********************************************************************/
1655 static void api_samr_connect( uint16 vuid, prs_struct *data, prs_struct *rdata)
1656 {
1657         SAMR_Q_CONNECT q_u;
1658
1659         /* grab the samr open policy */
1660         samr_io_q_connect("", &q_u, data, 0);
1661
1662         /* construct reply.  always indicate success */
1663         samr_reply_connect(&q_u, rdata);
1664 }
1665
1666 /*******************************************************************
1667  samr_reply_open_alias
1668  ********************************************************************/
1669 static void samr_reply_open_alias(SAMR_Q_OPEN_ALIAS *q_u,
1670                                 prs_struct *rdata)
1671 {
1672         SAMR_R_OPEN_ALIAS r_u;
1673         BOOL pol_open = False;
1674
1675         /* set up the SAMR open_alias response */
1676
1677         r_u.status = 0x0;
1678         /* get a (unique) handle.  open a policy on it. */
1679         if (r_u.status == 0x0 && !(pol_open = open_lsa_policy_hnd(&(r_u.pol))))
1680         {
1681                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
1682         }
1683
1684         /* associate a RID with the (unique) handle. */
1685         if (r_u.status == 0x0 && !set_lsa_policy_samr_rid(&(r_u.pol), q_u->rid_alias))
1686         {
1687                 /* oh, whoops.  don't know what error message to return, here */
1688                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
1689         }
1690
1691         if (r_u.status != 0 && pol_open)
1692         {
1693                 close_lsa_policy_hnd(&(r_u.pol));
1694         }
1695
1696         DEBUG(5,("samr_open_alias: %d\n", __LINE__));
1697
1698         /* store the response in the SMB stream */
1699         samr_io_r_open_alias("", &r_u, rdata, 0);
1700
1701         DEBUG(5,("samr_open_alias: %d\n", __LINE__));
1702
1703 }
1704
1705 /*******************************************************************
1706  api_samr_open_alias
1707  ********************************************************************/
1708 static void api_samr_open_alias( uint16 vuid, prs_struct *data, prs_struct *rdata)
1709                                 
1710 {
1711         SAMR_Q_OPEN_ALIAS q_u;
1712
1713         /* grab the samr open policy */
1714         samr_io_q_open_alias("", &q_u, data, 0);
1715
1716         /* construct reply.  always indicate success */
1717         samr_reply_open_alias(&q_u, rdata);
1718 }
1719
1720 /*******************************************************************
1721  array of \PIPE\samr operations
1722  ********************************************************************/
1723 static struct api_struct api_samr_cmds [] =
1724 {
1725         { "SAMR_CLOSE_HND"        , SAMR_CLOSE_HND        , api_samr_close_hnd        },
1726         { "SAMR_CONNECT"          , SAMR_CONNECT          , api_samr_connect          },
1727         { "SAMR_CONNECT_ANON"     , SAMR_CONNECT_ANON     , api_samr_connect_anon     },
1728         { "SAMR_ENUM_DOM_USERS"   , SAMR_ENUM_DOM_USERS   , api_samr_enum_dom_users   },
1729         { "SAMR_ENUM_DOM_GROUPS"  , SAMR_ENUM_DOM_GROUPS  , api_samr_enum_dom_groups  },
1730         { "SAMR_ENUM_DOM_ALIASES" , SAMR_ENUM_DOM_ALIASES , api_samr_enum_dom_aliases },
1731         { "SAMR_LOOKUP_IDS"       , SAMR_LOOKUP_IDS       , api_samr_lookup_ids       },
1732         { "SAMR_LOOKUP_NAMES"     , SAMR_LOOKUP_NAMES     , api_samr_lookup_names     },
1733         { "SAMR_OPEN_USER"        , SAMR_OPEN_USER        , api_samr_open_user        },
1734         { "SAMR_QUERY_USERINFO"   , SAMR_QUERY_USERINFO   , api_samr_query_userinfo   },
1735         { "SAMR_QUERY_DOMAIN_INFO", SAMR_QUERY_DOMAIN_INFO, api_samr_query_dom_info        },
1736         { "SAMR_QUERY_USERGROUPS" , SAMR_QUERY_USERGROUPS , api_samr_query_usergroups },
1737         { "SAMR_QUERY_DISPINFO"   , SAMR_QUERY_DISPINFO   , api_samr_query_dispinfo   },
1738         { "SAMR_QUERY_ALIASINFO"  , SAMR_QUERY_ALIASINFO  , api_samr_query_aliasinfo  },
1739         { "SAMR_0x32"             , 0x32                  , api_samr_unknown_32       },
1740         { "SAMR_UNKNOWN_12"       , SAMR_UNKNOWN_12       , api_samr_unknown_12       },
1741         { "SAMR_UNKNOWN_38"       , SAMR_UNKNOWN_38       , api_samr_unknown_38       },
1742         { "SAMR_CHGPASSWD_USER"   , SAMR_CHGPASSWD_USER   , api_samr_chgpasswd_user   },
1743         { "SAMR_OPEN_ALIAS"       , SAMR_OPEN_ALIAS       , api_samr_open_alias       },
1744         { "SAMR_OPEN_DOMAIN"      , SAMR_OPEN_DOMAIN      , api_samr_open_domain      },
1745         { "SAMR_UNKNOWN_3"        , SAMR_UNKNOWN_3        , api_samr_unknown_3        },
1746         { "SAMR_UNKNOWN_2C"       , SAMR_UNKNOWN_2C       , api_samr_unknown_2c       },
1747         { NULL                    , 0                     , NULL                      }
1748 };
1749
1750 /*******************************************************************
1751  receives a samr pipe and responds.
1752  ********************************************************************/
1753 BOOL api_samr_rpc(pipes_struct *p, prs_struct *data)
1754 {
1755     return api_rpcTNP(p, "api_samr_rpc", api_samr_cmds, data);
1756 }
1757