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