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