7e725f3599b1f92997549dbb8e5ff901d7fb8aa9
[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;
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                         BOOL ret;
815
816                         DEBUG(5,("lookup on Domain SID\n"));
817
818                         become_root(True);
819                         ret = getusergroupsnam(sam_pass->smb_name, &mem_grp, &num_rids);
820                         unbecome_root(True);
821
822                         num_rids = MIN(num_rids, MAX_SAM_ENTRIES);
823
824                         if (mem_grp != NULL)
825                         {
826                                 for (i = 0; i < num_rids; i++)
827                                 {
828                                         rid[i] = mem_grp[i].rid;
829                                 }
830                                 free(mem_grp);
831                         }
832                 }
833                 else
834                 {
835                         status = 0xC0000000 | NT_STATUS_NO_SUCH_USER;
836                 }
837         }
838
839         make_samr_r_lookup_ids(&r_u, num_rids, rid, status);
840
841         /* store the response in the SMB stream */
842         samr_io_r_lookup_ids("", &r_u, rdata, 0);
843
844         DEBUG(5,("samr_lookup_ids: %d\n", __LINE__));
845
846 }
847
848 /*******************************************************************
849  api_samr_lookup_ids
850  ********************************************************************/
851 static void api_samr_lookup_ids( uint16 vuid, prs_struct *data, prs_struct *rdata)
852 {
853         SAMR_Q_LOOKUP_IDS q_u;
854
855         /* grab the samr 0x10 */
856         samr_io_q_lookup_ids("", &q_u, data, 0);
857
858         /* construct reply.  always indicate success */
859         samr_reply_lookup_ids(&q_u, rdata);
860 }
861
862 /*******************************************************************
863  samr_reply_lookup_names
864  ********************************************************************/
865 static void samr_reply_lookup_names(SAMR_Q_LOOKUP_NAMES *q_u,
866                                 prs_struct *rdata)
867 {
868         uint32 rid [MAX_SAM_ENTRIES];
869         uint8  type[MAX_SAM_ENTRIES];
870         uint32 status     = 0;
871         int i;
872         int num_rids = q_u->num_rids1;
873
874         SAMR_R_LOOKUP_NAMES r_u;
875
876         DEBUG(5,("samr_lookup_names: %d\n", __LINE__));
877
878         if (num_rids > MAX_SAM_ENTRIES)
879         {
880                 num_rids = MAX_SAM_ENTRIES;
881                 DEBUG(5,("samr_lookup_names: truncating entries to %d\n", num_rids));
882         }
883
884         SMB_ASSERT_ARRAY(q_u->uni_user_name, num_rids);
885
886         for (i = 0; i < num_rids && status == 0; i++)
887         {
888                 DOM_SID sid;
889                 fstring name;
890                 fstrcpy(name, unistrn2(q_u->uni_user_name[i].buffer, q_u->uni_user_name[i].uni_str_len));
891
892                 status = lookup_name(name, &sid, &(type[i]));
893                 if (status == 0x0)
894                 {
895                         sid_split_rid(&sid, &rid[i]);
896                 }
897                 else
898                 {
899                         type[i] = SID_NAME_UNKNOWN;
900                 }
901         }
902
903         make_samr_r_lookup_names(&r_u, num_rids, rid, type, status);
904
905         /* store the response in the SMB stream */
906         samr_io_r_lookup_names("", &r_u, rdata, 0);
907
908         DEBUG(5,("samr_lookup_names: %d\n", __LINE__));
909
910 }
911
912 /*******************************************************************
913  api_samr_lookup_names
914  ********************************************************************/
915 static void api_samr_lookup_names( uint16 vuid, prs_struct *data, prs_struct *rdata)
916 {
917         SAMR_Q_LOOKUP_NAMES q_u;
918
919         /* grab the samr lookup names */
920         samr_io_q_lookup_names("", &q_u, data, 0);
921
922         /* construct reply.  always indicate success */
923         samr_reply_lookup_names(&q_u, rdata);
924 }
925
926 /*******************************************************************
927  samr_reply_chgpasswd_user
928  ********************************************************************/
929 static void samr_reply_chgpasswd_user(SAMR_Q_CHGPASSWD_USER *q_u,
930                                 prs_struct *rdata)
931 {
932         SAMR_R_CHGPASSWD_USER r_u;
933         uint32 status = 0x0;
934         fstring user_name;
935         fstring wks;
936
937         fstrcpy(user_name, unistrn2(q_u->uni_user_name.buffer, q_u->uni_user_name.uni_str_len));
938         fstrcpy(wks      , unistrn2(q_u->uni_dest_host.buffer, q_u->uni_dest_host.uni_str_len));
939
940         DEBUG(5,("samr_chgpasswd_user: user: %s wks: %s\n", user_name, wks));
941
942         if (!pass_oem_change(user_name,
943                              q_u->lm_newpass.pass, q_u->lm_oldhash.hash,
944                              q_u->nt_newpass.pass, q_u->nt_oldhash.hash))
945         {
946                 status = 0xC0000000 | NT_STATUS_WRONG_PASSWORD;
947         }
948
949         make_samr_r_chgpasswd_user(&r_u, status);
950
951         /* store the response in the SMB stream */
952         samr_io_r_chgpasswd_user("", &r_u, rdata, 0);
953
954         DEBUG(5,("samr_chgpasswd_user: %d\n", __LINE__));
955 }
956
957 /*******************************************************************
958  api_samr_chgpasswd_user
959  ********************************************************************/
960 static void api_samr_chgpasswd_user( uint16 vuid, prs_struct *data, prs_struct *rdata)
961 {
962         SAMR_Q_CHGPASSWD_USER q_u;
963
964         /* unknown 38 command */
965         samr_io_q_chgpasswd_user("", &q_u, data, 0);
966
967         /* construct reply. */
968         samr_reply_chgpasswd_user(&q_u, rdata);
969 }
970
971
972 /*******************************************************************
973  samr_reply_unknown_38
974  ********************************************************************/
975 static void samr_reply_unknown_38(SAMR_Q_UNKNOWN_38 *q_u,
976                                 prs_struct *rdata)
977 {
978         SAMR_R_UNKNOWN_38 r_u;
979
980         DEBUG(5,("samr_unknown_38: %d\n", __LINE__));
981
982         make_samr_r_unknown_38(&r_u);
983
984         /* store the response in the SMB stream */
985         samr_io_r_unknown_38("", &r_u, rdata, 0);
986
987         DEBUG(5,("samr_unknown_38: %d\n", __LINE__));
988 }
989
990 /*******************************************************************
991  api_samr_unknown_38
992  ********************************************************************/
993 static void api_samr_unknown_38( uint16 vuid, prs_struct *data, prs_struct *rdata)
994 {
995         SAMR_Q_UNKNOWN_38 q_u;
996
997         /* unknown 38 command */
998         samr_io_q_unknown_38("", &q_u, data, 0);
999
1000         /* construct reply.  always indicate success */
1001         samr_reply_unknown_38(&q_u, rdata);
1002 }
1003
1004
1005 /*******************************************************************
1006  samr_reply_unknown_12
1007  ********************************************************************/
1008 static void samr_reply_unknown_12(SAMR_Q_UNKNOWN_12 *q_u,
1009                                 prs_struct *rdata)
1010 {
1011         fstring group_names[MAX_SAM_ENTRIES];
1012         uint8   group_attrs[MAX_SAM_ENTRIES];
1013         uint32 status     = 0;
1014         int num_gids = q_u->num_gids1;
1015         DOM_SID pol_sid;
1016
1017         SAMR_R_UNKNOWN_12 r_u;
1018
1019         DEBUG(5,("samr_unknown_12: %d\n", __LINE__));
1020
1021         /* find the policy handle.  open a policy on it. */
1022         if (status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->pol)) == -1))
1023         {
1024                 status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
1025         }
1026
1027         if (status == 0x0 && !get_lsa_policy_samr_sid(&q_u->pol, &pol_sid))
1028         {
1029                 status = NT_STATUS_OBJECT_TYPE_MISMATCH;
1030         }
1031
1032         if (status == 0x0)
1033         {
1034                 int i;
1035                 if (num_gids > MAX_SAM_ENTRIES)
1036                 {
1037                         num_gids = MAX_SAM_ENTRIES;
1038                         DEBUG(5,("samr_unknown_12: truncating entries to %d\n", num_gids));
1039                 }
1040
1041                 for (i = 0; i < num_gids && status == 0; i++)
1042                 {
1043                         DOM_SID sid;
1044                         sid_copy(&sid, &pol_sid);
1045                         sid_append_rid(&sid, q_u->gid[i]);
1046                         lookup_sid(&sid, group_names[i], &group_attrs[i]);
1047                         group_attrs[i] = 0x2;
1048                 }
1049         }
1050
1051         make_samr_r_unknown_12(&r_u, num_gids, group_names, group_attrs, status);
1052
1053         /* store the response in the SMB stream */
1054         samr_io_r_unknown_12("", &r_u, rdata, 0);
1055
1056         DEBUG(5,("samr_unknown_12: %d\n", __LINE__));
1057
1058 }
1059
1060 /*******************************************************************
1061  api_samr_unknown_12
1062  ********************************************************************/
1063 static void api_samr_unknown_12( uint16 vuid, prs_struct *data, prs_struct *rdata)
1064 {
1065         SAMR_Q_UNKNOWN_12 q_u;
1066
1067         /* grab the samr lookup names */
1068         samr_io_q_unknown_12("", &q_u, data, 0);
1069
1070         /* construct reply.  always indicate success */
1071         samr_reply_unknown_12(&q_u, rdata);
1072 }
1073
1074
1075 /*******************************************************************
1076  samr_reply_open_user
1077  ********************************************************************/
1078 static void samr_reply_open_user(SAMR_Q_OPEN_USER *q_u,
1079                                 prs_struct *rdata,
1080                                 int status)
1081 {
1082         SAMR_R_OPEN_USER r_u;
1083         struct sam_passwd *sam_pass;
1084         BOOL pol_open = False;
1085
1086         /* set up the SAMR open_user response */
1087         bzero(r_u.user_pol.data, POL_HND_SIZE);
1088
1089         r_u.status = 0x0;
1090
1091         /* find the policy handle.  open a policy on it. */
1092         if (r_u.status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->domain_pol)) == -1))
1093         {
1094                 r_u.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
1095         }
1096
1097         /* get a (unique) handle.  open a policy on it. */
1098         if (r_u.status == 0x0 && !(pol_open = open_lsa_policy_hnd(&(r_u.user_pol))))
1099         {
1100                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
1101         }
1102
1103         become_root(True);
1104         sam_pass = getsam21pwrid(q_u->user_rid);
1105         unbecome_root(True);
1106
1107         /* check that the RID exists in our domain. */
1108         if (r_u.status == 0x0 && sam_pass == NULL)
1109         {
1110                 r_u.status = 0xC0000000 | NT_STATUS_NO_SUCH_USER;
1111         }
1112
1113         /* associate the RID with the (unique) handle. */
1114         if (r_u.status == 0x0 && !set_lsa_policy_samr_rid(&(r_u.user_pol), q_u->user_rid))
1115         {
1116                 /* oh, whoops.  don't know what error message to return, here */
1117                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
1118         }
1119
1120         if (r_u.status != 0 && pol_open)
1121         {
1122                 close_lsa_policy_hnd(&(r_u.user_pol));
1123         }
1124
1125         DEBUG(5,("samr_open_user: %d\n", __LINE__));
1126
1127         /* store the response in the SMB stream */
1128         samr_io_r_open_user("", &r_u, rdata, 0);
1129
1130         DEBUG(5,("samr_open_user: %d\n", __LINE__));
1131
1132 }
1133
1134 /*******************************************************************
1135  api_samr_open_user
1136  ********************************************************************/
1137 static void api_samr_open_user( uint16 vuid, prs_struct *data, prs_struct *rdata)
1138 {
1139         SAMR_Q_OPEN_USER q_u;
1140
1141         /* grab the samr unknown 22 */
1142         samr_io_q_open_user("", &q_u, data, 0);
1143
1144         /* construct reply.  always indicate success */
1145         samr_reply_open_user(&q_u, rdata, 0x0);
1146 }
1147
1148
1149 /*************************************************************************
1150  get_user_info_10
1151  *************************************************************************/
1152 static BOOL get_user_info_10(SAM_USER_INFO_10 *id10, uint32 user_rid)
1153 {
1154         struct smb_passwd *smb_pass;
1155
1156         if (!pwdb_rid_is_user(user_rid))
1157         {
1158                 DEBUG(4,("RID 0x%x is not a user RID\n", user_rid));
1159                 return False;
1160         }
1161
1162         become_root(True);
1163         smb_pass = getsmbpwrid(user_rid);
1164         unbecome_root(True);
1165
1166         if (smb_pass == NULL)
1167         {
1168                 DEBUG(4,("User 0x%x not found\n", user_rid));
1169                 return False;
1170         }
1171
1172         DEBUG(3,("User:[%s]\n", smb_pass->smb_name));
1173
1174         make_sam_user_info10(id10, smb_pass->acct_ctrl); 
1175
1176         return True;
1177 }
1178
1179 /*************************************************************************
1180  get_user_info_21
1181  *************************************************************************/
1182 static BOOL get_user_info_21(SAM_USER_INFO_21 *id21, uint32 user_rid)
1183 {
1184         NTTIME dummy_time;
1185         struct sam_passwd *sam_pass;
1186         LOGON_HRS hrs;
1187         int i;
1188
1189         if (!pwdb_rid_is_user(user_rid))
1190         {
1191                 DEBUG(4,("RID 0x%x is not a user RID\n", user_rid));
1192                 return False;
1193         }
1194
1195         become_root(True);
1196         sam_pass = getsam21pwrid(user_rid);
1197         unbecome_root(True);
1198
1199         if (sam_pass == NULL)
1200         {
1201                 DEBUG(4,("User 0x%x not found\n", user_rid));
1202                 return False;
1203         }
1204
1205         DEBUG(3,("User:[%s]\n", sam_pass->smb_name));
1206
1207         dummy_time.low  = 0xffffffff;
1208         dummy_time.high = 0x7fffffff;
1209
1210         DEBUG(0,("get_user_info_21 - TODO: convert unix times to NTTIMEs\n"));
1211
1212         /* create a LOGON_HRS structure */
1213         hrs.len = sam_pass->hours_len;
1214         SMB_ASSERT_ARRAY(hrs.hours, hrs.len);
1215         for (i = 0; i < hrs.len; i++)
1216         {
1217                 hrs.hours[i] = sam_pass->hours[i];
1218         }
1219
1220         make_sam_user_info21(id21,
1221
1222                            &dummy_time, /* logon_time */
1223                            &dummy_time, /* logoff_time */
1224                            &dummy_time, /* kickoff_time */
1225                            &dummy_time, /* pass_last_set_time */
1226                            &dummy_time, /* pass_can_change_time */
1227                            &dummy_time, /* pass_must_change_time */
1228
1229                            sam_pass->smb_name, /* user_name */
1230                            sam_pass->full_name, /* full_name */
1231                            sam_pass->home_dir, /* home_dir */
1232                            sam_pass->dir_drive, /* dir_drive */
1233                            sam_pass->logon_script, /* logon_script */
1234                            sam_pass->profile_path, /* profile_path */
1235                            sam_pass->acct_desc, /* description */
1236                            sam_pass->workstations, /* workstations user can log in from */
1237                            sam_pass->unknown_str, /* don't know, yet */
1238                            sam_pass->munged_dial, /* dialin info.  contains dialin path and tel no */
1239
1240                            sam_pass->user_rid, /* RID user_id */
1241                            sam_pass->group_rid, /* RID group_id */
1242                        sam_pass->acct_ctrl,
1243
1244                    sam_pass->unknown_3, /* unknown_3 */
1245                        sam_pass->logon_divs, /* divisions per week */
1246                            &hrs, /* logon hours */
1247                        sam_pass->unknown_5,
1248                        sam_pass->unknown_6);
1249
1250         return True;
1251 }
1252
1253 /*******************************************************************
1254  samr_reply_query_userinfo
1255  ********************************************************************/
1256 static void samr_reply_query_userinfo(SAMR_Q_QUERY_USERINFO *q_u,
1257                                 prs_struct *rdata)
1258 {
1259         SAMR_R_QUERY_USERINFO r_u;
1260 #if 0
1261         SAM_USER_INFO_11 id11;
1262 #endif
1263         SAM_USER_INFO_10 id10;
1264         SAM_USER_INFO_21 id21;
1265         void *info = NULL;
1266
1267         uint32 status = 0x0;
1268         uint32 rid = 0x0;
1269
1270         DEBUG(5,("samr_reply_query_userinfo: %d\n", __LINE__));
1271
1272         /* search for the handle */
1273         if (status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->pol)) == -1))
1274         {
1275                 status = NT_STATUS_INVALID_HANDLE;
1276         }
1277
1278         /* find the user's rid */
1279         if (status == 0x0 && (rid = get_lsa_policy_samr_rid(&(q_u->pol))) == 0xffffffff)
1280         {
1281                 status = NT_STATUS_OBJECT_TYPE_MISMATCH;
1282         }
1283
1284         DEBUG(5,("samr_reply_query_userinfo: rid:0x%x\n", rid));
1285
1286         /* ok!  user info levels (there are lots: see MSDEV help), off we go... */
1287         if (status == 0x0)
1288         {
1289                 switch (q_u->switch_value)
1290                 {
1291                         case 0x10:
1292                         {
1293                                 info = (void*)&id10;
1294                                 status = get_user_info_10(&id10, rid) ? 0 : NT_STATUS_NO_SUCH_USER;
1295                                 break;
1296                         }
1297 #if 0
1298 /* whoops - got this wrong.  i think.  or don't understand what's happening. */
1299                         case 0x11:
1300                         {
1301                                 NTTIME expire;
1302                                 info = (void*)&id11;
1303                                 
1304                                 expire.low  = 0xffffffff;
1305                                 expire.high = 0x7fffffff;
1306
1307                                 make_sam_user_info11(&id11, &expire, "BROOKFIELDS$", 0x03ef, 0x201, 0x0080);
1308
1309                                 break;
1310                         }
1311 #endif
1312                         case 21:
1313                         {
1314                                 info = (void*)&id21;
1315                                 status = get_user_info_21(&id21, rid) ? 0 : NT_STATUS_NO_SUCH_USER;
1316                                 break;
1317                         }
1318
1319                         default:
1320                         {
1321                                 status = NT_STATUS_INVALID_INFO_CLASS;
1322
1323                                 break;
1324                         }
1325                 }
1326         }
1327
1328         make_samr_r_query_userinfo(&r_u, q_u->switch_value, info, status);
1329
1330         /* store the response in the SMB stream */
1331         samr_io_r_query_userinfo("", &r_u, rdata, 0);
1332
1333         DEBUG(5,("samr_reply_query_userinfo: %d\n", __LINE__));
1334
1335 }
1336
1337 /*******************************************************************
1338  api_samr_query_userinfo
1339  ********************************************************************/
1340 static void api_samr_query_userinfo( uint16 vuid, prs_struct *data, prs_struct *rdata)
1341 {
1342         SAMR_Q_QUERY_USERINFO q_u;
1343
1344         /* grab the samr unknown 24 */
1345         samr_io_q_query_userinfo("", &q_u, data, 0);
1346
1347         /* construct reply.  always indicate success */
1348         samr_reply_query_userinfo(&q_u, rdata);
1349 }
1350
1351
1352 /*******************************************************************
1353  samr_reply_query_usergroups
1354  ********************************************************************/
1355 static void samr_reply_query_usergroups(SAMR_Q_QUERY_USERGROUPS *q_u,
1356                                 prs_struct *rdata)
1357 {
1358         SAMR_R_QUERY_USERGROUPS r_u;
1359         uint32 status = 0x0;
1360
1361         struct sam_passwd *sam_pass;
1362         DOM_GID *gids = NULL;
1363         int num_groups = 0;
1364         uint32 rid;
1365
1366         DEBUG(5,("samr_query_usergroups: %d\n", __LINE__));
1367
1368         /* find the policy handle.  open a policy on it. */
1369         if (status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->pol)) == -1))
1370         {
1371                 status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
1372         }
1373
1374         /* find the user's rid */
1375         if (status == 0x0 && (rid = get_lsa_policy_samr_rid(&(q_u->pol))) == 0xffffffff)
1376         {
1377                 status = NT_STATUS_OBJECT_TYPE_MISMATCH;
1378         }
1379
1380         if (status == 0x0)
1381         {
1382                 become_root(True);
1383                 sam_pass = getsam21pwrid(rid);
1384                 unbecome_root(True);
1385
1386                 if (sam_pass == NULL)
1387                 {
1388                         status = 0xC0000000 | NT_STATUS_NO_SUCH_USER;
1389                 }
1390         }
1391
1392         if (status == 0x0)
1393         {
1394                 DOMAIN_GRP *mem_grp = NULL;
1395                 BOOL ret;
1396
1397                 become_root(True);
1398                 ret = getusergroupsnam(sam_pass->smb_name, &mem_grp, &num_groups);
1399                 unbecome_root(True);
1400
1401                 gids = NULL;
1402                 num_groups = make_dom_gids(mem_grp, num_groups, &gids);
1403
1404                 if (mem_grp != NULL)
1405                 {
1406                         free(mem_grp);
1407                 }
1408         }
1409
1410         /* construct the response.  lkclXXXX: gids are not copied! */
1411         make_samr_r_query_usergroups(&r_u, num_groups, gids, status);
1412
1413         /* store the response in the SMB stream */
1414         samr_io_r_query_usergroups("", &r_u, rdata, 0);
1415
1416         if (gids)
1417         {
1418                 free((char *)gids);
1419         }
1420
1421         DEBUG(5,("samr_query_usergroups: %d\n", __LINE__));
1422
1423 }
1424
1425 /*******************************************************************
1426  api_samr_query_usergroups
1427  ********************************************************************/
1428 static void api_samr_query_usergroups( uint16 vuid, prs_struct *data, prs_struct *rdata)
1429 {
1430         SAMR_Q_QUERY_USERGROUPS q_u;
1431         /* grab the samr unknown 32 */
1432         samr_io_q_query_usergroups("", &q_u, data, 0);
1433
1434         /* construct reply. */
1435         samr_reply_query_usergroups(&q_u, rdata);
1436 }
1437
1438
1439 /*******************************************************************
1440  samr_reply_query_dom_info
1441  ********************************************************************/
1442 static void samr_reply_query_dom_info(SAMR_Q_QUERY_DOMAIN_INFO *q_u,
1443                                 prs_struct *rdata)
1444 {
1445         SAMR_R_QUERY_DOMAIN_INFO r_u;
1446         SAM_UNK_CTR ctr;
1447         uint16 switch_value = 0x0;
1448         uint32 status = 0x0;
1449
1450         ZERO_STRUCT(r_u);
1451         ZERO_STRUCT(ctr);
1452
1453         r_u.ctr = &ctr;
1454
1455         DEBUG(5,("samr_reply_query_dom_info: %d\n", __LINE__));
1456
1457         /* find the policy handle.  open a policy on it. */
1458         if (r_u.status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->domain_pol)) == -1))
1459         {
1460                 r_u.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
1461                 DEBUG(5,("samr_reply_query_dom_info: invalid handle\n"));
1462         }
1463
1464         if (status == 0x0)
1465         {
1466                 switch (q_u->switch_value)
1467                 {
1468                         case 0x02:
1469                         {
1470                                 switch_value = 0x2;
1471                                 make_unk_info2(&ctr.info.inf2, global_sam_name, global_myname);
1472
1473                                 break;
1474                         }
1475                         default:
1476                         {
1477                                 status = 0xC0000000 | NT_STATUS_INVALID_INFO_CLASS;
1478                                 break;
1479                         }
1480                 }
1481         }
1482
1483         make_samr_r_query_dom_info(&r_u, switch_value, &ctr, status);
1484
1485         /* store the response in the SMB stream */
1486         samr_io_r_query_dom_info("", &r_u, rdata, 0);
1487
1488         DEBUG(5,("samr_query_dom_info: %d\n", __LINE__));
1489
1490 }
1491
1492 /*******************************************************************
1493  api_samr_query_dom_info
1494  ********************************************************************/
1495 static void api_samr_query_dom_info( uint16 vuid, prs_struct *data, prs_struct *rdata)
1496 {
1497         SAMR_Q_QUERY_DOMAIN_INFO q_e;
1498
1499         /* grab the samr unknown 8 command */
1500         samr_io_q_query_dom_info("", &q_e, data, 0);
1501
1502         /* construct reply. */
1503         samr_reply_query_dom_info(&q_e, rdata);
1504 }
1505
1506
1507
1508 /*******************************************************************
1509  samr_reply_unknown_32
1510  ********************************************************************/
1511 static void samr_reply_unknown_32(SAMR_Q_UNKNOWN_32 *q_u,
1512                                 prs_struct *rdata,
1513                                 int status)
1514 {
1515         int i;
1516         SAMR_R_UNKNOWN_32 r_u;
1517
1518         /* set up the SAMR unknown_32 response */
1519         bzero(r_u.pol.data, POL_HND_SIZE);
1520         if (status == 0)
1521         {
1522                 for (i = 4; i < POL_HND_SIZE; i++)
1523                 {
1524                         r_u.pol.data[i] = i+1;
1525                 }
1526         }
1527
1528         make_dom_rid4(&(r_u.rid4), 0x0030, 0, 0);
1529         r_u.status    = status;
1530
1531         DEBUG(5,("samr_unknown_32: %d\n", __LINE__));
1532
1533         /* store the response in the SMB stream */
1534         samr_io_r_unknown_32("", &r_u, rdata, 0);
1535
1536         DEBUG(5,("samr_unknown_32: %d\n", __LINE__));
1537
1538 }
1539
1540 /*******************************************************************
1541  api_samr_unknown_32
1542  ********************************************************************/
1543 static void api_samr_unknown_32( uint16 vuid, prs_struct *data, prs_struct *rdata)
1544 {
1545         uint32 status = 0;
1546         struct sam_passwd *sam_pass;
1547         fstring mach_acct;
1548
1549         SAMR_Q_UNKNOWN_32 q_u;
1550
1551         /* grab the samr unknown 32 */
1552         samr_io_q_unknown_32("", &q_u, data, 0);
1553
1554         /* find the machine account: tell the caller if it exists.
1555            lkclXXXX i have *no* idea if this is a problem or not
1556            or even if you are supposed to construct a different
1557            reply if the account already exists...
1558          */
1559
1560         fstrcpy(mach_acct, unistrn2(q_u.uni_mach_acct.buffer,
1561                                     q_u.uni_mach_acct.uni_str_len));
1562
1563         become_root(True);
1564         sam_pass = getsam21pwnam(mach_acct);
1565         unbecome_root(True);
1566
1567         if (sam_pass != NULL)
1568         {
1569                 /* machine account exists: say so */
1570                 status = 0xC0000000 | NT_STATUS_USER_EXISTS;
1571         }
1572         else
1573         {
1574                 /* this could cause trouble... */
1575                 DEBUG(0,("trouble!\n"));
1576                 status = 0;
1577         }
1578
1579         /* construct reply. */
1580         samr_reply_unknown_32(&q_u, rdata, status);
1581 }
1582
1583
1584 /*******************************************************************
1585  samr_reply_connect_anon
1586  ********************************************************************/
1587 static void samr_reply_connect_anon(SAMR_Q_CONNECT_ANON *q_u,
1588                                 prs_struct *rdata)
1589 {
1590         SAMR_R_CONNECT_ANON r_u;
1591         BOOL pol_open = False;
1592
1593         /* set up the SAMR connect_anon response */
1594
1595         r_u.status = 0x0;
1596         /* get a (unique) handle.  open a policy on it. */
1597         if (r_u.status == 0x0 && !(pol_open = open_lsa_policy_hnd(&(r_u.connect_pol))))
1598         {
1599                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
1600         }
1601
1602         /* associate the domain SID with the (unique) handle. */
1603         if (r_u.status == 0x0 && !set_lsa_policy_samr_pol_status(&(r_u.connect_pol), q_u->unknown_0))
1604         {
1605                 /* oh, whoops.  don't know what error message to return, here */
1606                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
1607         }
1608
1609         if (r_u.status != 0 && pol_open)
1610         {
1611                 close_lsa_policy_hnd(&(r_u.connect_pol));
1612         }
1613
1614         DEBUG(5,("samr_connect_anon: %d\n", __LINE__));
1615
1616         /* store the response in the SMB stream */
1617         samr_io_r_connect_anon("", &r_u, rdata, 0);
1618
1619         DEBUG(5,("samr_connect_anon: %d\n", __LINE__));
1620
1621 }
1622
1623 /*******************************************************************
1624  api_samr_connect_anon
1625  ********************************************************************/
1626 static void api_samr_connect_anon( uint16 vuid, prs_struct *data, prs_struct *rdata)
1627 {
1628         SAMR_Q_CONNECT_ANON q_u;
1629
1630         /* grab the samr open policy */
1631         samr_io_q_connect_anon("", &q_u, data, 0);
1632
1633         /* construct reply.  always indicate success */
1634         samr_reply_connect_anon(&q_u, rdata);
1635 }
1636
1637 /*******************************************************************
1638  samr_reply_connect
1639  ********************************************************************/
1640 static void samr_reply_connect(SAMR_Q_CONNECT *q_u,
1641                                 prs_struct *rdata)
1642 {
1643         SAMR_R_CONNECT r_u;
1644         BOOL pol_open = False;
1645
1646         /* set up the SAMR connect response */
1647
1648         r_u.status = 0x0;
1649         /* get a (unique) handle.  open a policy on it. */
1650         if (r_u.status == 0x0 && !(pol_open = open_lsa_policy_hnd(&(r_u.connect_pol))))
1651         {
1652                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
1653         }
1654
1655         /* associate the domain SID with the (unique) handle. */
1656         if (r_u.status == 0x0 && !set_lsa_policy_samr_pol_status(&(r_u.connect_pol), q_u->unknown_0))
1657         {
1658                 /* oh, whoops.  don't know what error message to return, here */
1659                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
1660         }
1661
1662         if (r_u.status != 0 && pol_open)
1663         {
1664                 close_lsa_policy_hnd(&(r_u.connect_pol));
1665         }
1666
1667         DEBUG(5,("samr_connect: %d\n", __LINE__));
1668
1669         /* store the response in the SMB stream */
1670         samr_io_r_connect("", &r_u, rdata, 0);
1671
1672         DEBUG(5,("samr_connect: %d\n", __LINE__));
1673
1674 }
1675
1676 /*******************************************************************
1677  api_samr_connect
1678  ********************************************************************/
1679 static void api_samr_connect( uint16 vuid, prs_struct *data, prs_struct *rdata)
1680 {
1681         SAMR_Q_CONNECT q_u;
1682
1683         /* grab the samr open policy */
1684         samr_io_q_connect("", &q_u, data, 0);
1685
1686         /* construct reply.  always indicate success */
1687         samr_reply_connect(&q_u, rdata);
1688 }
1689
1690 /*******************************************************************
1691  samr_reply_open_alias
1692  ********************************************************************/
1693 static void samr_reply_open_alias(SAMR_Q_OPEN_ALIAS *q_u,
1694                                 prs_struct *rdata)
1695 {
1696         SAMR_R_OPEN_ALIAS r_u;
1697         BOOL pol_open = False;
1698
1699         /* set up the SAMR open_alias response */
1700
1701         r_u.status = 0x0;
1702         /* get a (unique) handle.  open a policy on it. */
1703         if (r_u.status == 0x0 && !(pol_open = open_lsa_policy_hnd(&(r_u.pol))))
1704         {
1705                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
1706         }
1707
1708         /* associate a RID with the (unique) handle. */
1709         if (r_u.status == 0x0 && !set_lsa_policy_samr_rid(&(r_u.pol), q_u->rid_alias))
1710         {
1711                 /* oh, whoops.  don't know what error message to return, here */
1712                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
1713         }
1714
1715         if (r_u.status != 0 && pol_open)
1716         {
1717                 close_lsa_policy_hnd(&(r_u.pol));
1718         }
1719
1720         DEBUG(5,("samr_open_alias: %d\n", __LINE__));
1721
1722         /* store the response in the SMB stream */
1723         samr_io_r_open_alias("", &r_u, rdata, 0);
1724
1725         DEBUG(5,("samr_open_alias: %d\n", __LINE__));
1726
1727 }
1728
1729 /*******************************************************************
1730  api_samr_open_alias
1731  ********************************************************************/
1732 static void api_samr_open_alias( uint16 vuid, prs_struct *data, prs_struct *rdata)
1733                                 
1734 {
1735         SAMR_Q_OPEN_ALIAS q_u;
1736
1737         /* grab the samr open policy */
1738         samr_io_q_open_alias("", &q_u, data, 0);
1739
1740         /* construct reply.  always indicate success */
1741         samr_reply_open_alias(&q_u, rdata);
1742 }
1743
1744 /*******************************************************************
1745  array of \PIPE\samr operations
1746  ********************************************************************/
1747 static struct api_struct api_samr_cmds [] =
1748 {
1749         { "SAMR_CLOSE_HND"        , SAMR_CLOSE_HND        , api_samr_close_hnd        },
1750         { "SAMR_CONNECT"          , SAMR_CONNECT          , api_samr_connect          },
1751         { "SAMR_CONNECT_ANON"     , SAMR_CONNECT_ANON     , api_samr_connect_anon     },
1752         { "SAMR_ENUM_DOM_USERS"   , SAMR_ENUM_DOM_USERS   , api_samr_enum_dom_users   },
1753         { "SAMR_ENUM_DOM_GROUPS"  , SAMR_ENUM_DOM_GROUPS  , api_samr_enum_dom_groups  },
1754         { "SAMR_ENUM_DOM_ALIASES" , SAMR_ENUM_DOM_ALIASES , api_samr_enum_dom_aliases },
1755         { "SAMR_LOOKUP_IDS"       , SAMR_LOOKUP_IDS       , api_samr_lookup_ids       },
1756         { "SAMR_LOOKUP_NAMES"     , SAMR_LOOKUP_NAMES     , api_samr_lookup_names     },
1757         { "SAMR_OPEN_USER"        , SAMR_OPEN_USER        , api_samr_open_user        },
1758         { "SAMR_QUERY_USERINFO"   , SAMR_QUERY_USERINFO   , api_samr_query_userinfo   },
1759         { "SAMR_QUERY_DOMAIN_INFO", SAMR_QUERY_DOMAIN_INFO, api_samr_query_dom_info        },
1760         { "SAMR_QUERY_USERGROUPS" , SAMR_QUERY_USERGROUPS , api_samr_query_usergroups },
1761         { "SAMR_QUERY_DISPINFO"   , SAMR_QUERY_DISPINFO   , api_samr_query_dispinfo   },
1762         { "SAMR_QUERY_ALIASINFO"  , SAMR_QUERY_ALIASINFO  , api_samr_query_aliasinfo  },
1763         { "SAMR_0x32"             , 0x32                  , api_samr_unknown_32       },
1764         { "SAMR_UNKNOWN_12"       , SAMR_UNKNOWN_12       , api_samr_unknown_12       },
1765         { "SAMR_UNKNOWN_38"       , SAMR_UNKNOWN_38       , api_samr_unknown_38       },
1766         { "SAMR_CHGPASSWD_USER"   , SAMR_CHGPASSWD_USER   , api_samr_chgpasswd_user   },
1767         { "SAMR_OPEN_ALIAS"       , SAMR_OPEN_ALIAS       , api_samr_open_alias       },
1768         { "SAMR_OPEN_DOMAIN"      , SAMR_OPEN_DOMAIN      , api_samr_open_domain      },
1769         { "SAMR_UNKNOWN_3"        , SAMR_UNKNOWN_3        , api_samr_unknown_3        },
1770         { "SAMR_UNKNOWN_2C"       , SAMR_UNKNOWN_2C       , api_samr_unknown_2c       },
1771         { NULL                    , 0                     , NULL                      }
1772 };
1773
1774 /*******************************************************************
1775  receives a samr pipe and responds.
1776  ********************************************************************/
1777 BOOL api_samr_rpc(pipes_struct *p, prs_struct *data)
1778 {
1779     return api_rpcTNP(p, "api_samr_rpc", api_samr_cmds, data);
1780 }
1781