Added new define NT_STATUS_MORE_ENTRIES = 0x105.
[tprouty/samba.git] / source / 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_sam_name;
32 extern pstring global_myname;
33 extern DOM_SID global_sam_sid;
34 extern DOM_SID global_sid_S_1_1;
35 extern DOM_SID global_sid_S_1_5_20;
36
37 /*******************************************************************
38   This next function should be replaced with something that
39   dynamically returns the correct user info..... JRA.
40  ********************************************************************/
41
42 static BOOL get_sampwd_entries(SAM_USER_INFO_21 *pw_buf,
43                                 int start_idx,
44                                 int *total_entries, int *num_entries,
45                                 int max_num_entries,
46                                 uint16 acb_mask)
47 {
48         void *vp = NULL;
49         struct sam_passwd *pwd = NULL;
50
51         (*num_entries) = 0;
52         (*total_entries) = 0;
53
54         if (pw_buf == NULL) return False;
55
56         vp = startsmbpwent(False);
57         if (!vp)
58         {
59                 DEBUG(0, ("get_sampwd_entries: Unable to open SMB password database.\n"));
60                 return False;
61         }
62
63         while (((pwd = getsam21pwent(vp)) != NULL) && (*num_entries) < max_num_entries)
64         {
65                 int user_name_len;
66
67                 if (start_idx > 0)
68                 {
69                         /* skip the requested number of entries.
70                            not very efficient, but hey...
71                          */
72                         if (acb_mask == 0 || IS_BITS_SET_SOME(pwd->acct_ctrl, acb_mask))
73                         {
74                                 start_idx--;
75                         }
76                         continue;
77                 }
78
79                 user_name_len = strlen(pwd->nt_name);
80                 make_unistr2(&(pw_buf[(*num_entries)].uni_user_name), pwd->nt_name, user_name_len);
81                 make_uni_hdr(&(pw_buf[(*num_entries)].hdr_user_name), user_name_len);
82                 pw_buf[(*num_entries)].user_rid = pwd->user_rid;
83                 bzero( pw_buf[(*num_entries)].nt_pwd , 16);
84
85                 /* Now check if the NT compatible password is available. */
86                 if (pwd->smb_nt_passwd != NULL)
87                 {
88                         memcpy( pw_buf[(*num_entries)].nt_pwd , pwd->smb_nt_passwd, 16);
89                 }
90
91                 pw_buf[(*num_entries)].acb_info = (uint16)pwd->acct_ctrl;
92
93                 DEBUG(5, ("entry idx: %d user %s, rid 0x%x, acb %x",
94                           (*num_entries), pwd->nt_name,
95                           pwd->user_rid, pwd->acct_ctrl));
96
97                 if (acb_mask == 0 || IS_BITS_SET_SOME(pwd->acct_ctrl, acb_mask))
98                 {
99                         DEBUG(5,(" acb_mask %x accepts\n", acb_mask));
100                         (*num_entries)++;
101                 }
102                 else
103                 {
104                         DEBUG(5,(" acb_mask %x rejects\n", acb_mask));
105                 }
106
107                 (*total_entries)++;
108         }
109
110         endsmbpwent(vp);
111
112         return (*num_entries) > 0;
113 }
114
115 /*******************************************************************
116  samr_reply_unknown_1
117  ********************************************************************/
118 static void samr_reply_close_hnd(SAMR_Q_CLOSE_HND *q_u,
119                                 prs_struct *rdata)
120 {
121         SAMR_R_CLOSE_HND r_u;
122
123         /* set up the SAMR unknown_1 response */
124         bzero(r_u.pol.data, POL_HND_SIZE);
125
126         /* close the policy handle */
127         if (close_lsa_policy_hnd(&(q_u->pol)))
128         {
129                 r_u.status = 0;
130         }
131         else
132         {
133                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_INVALID;
134         }
135
136         DEBUG(5,("samr_reply_close_hnd: %d\n", __LINE__));
137
138         /* store the response in the SMB stream */
139         samr_io_r_close_hnd("", &r_u, rdata, 0);
140
141         DEBUG(5,("samr_reply_close_hnd: %d\n", __LINE__));
142
143 }
144
145 /*******************************************************************
146  api_samr_close_hnd
147  ********************************************************************/
148 static void api_samr_close_hnd( uint16 vuid, prs_struct *data, prs_struct *rdata)
149 {
150         SAMR_Q_CLOSE_HND q_u;
151         samr_io_q_close_hnd("", &q_u, data, 0);
152         samr_reply_close_hnd(&q_u, rdata);
153 }
154
155
156 /*******************************************************************
157  samr_reply_open_domain
158  ********************************************************************/
159 static void samr_reply_open_domain(SAMR_Q_OPEN_DOMAIN *q_u,
160                                 prs_struct *rdata)
161 {
162         SAMR_R_OPEN_DOMAIN r_u;
163         BOOL pol_open = False;
164
165         r_u.status = 0x0;
166
167         /* find the connection policy handle. */
168         if (r_u.status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->connect_pol)) == -1))
169         {
170                 r_u.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
171         }
172
173         /* get a (unique) handle.  open a policy on it. */
174         if (r_u.status == 0x0 && !(pol_open = open_lsa_policy_hnd(&(r_u.domain_pol))))
175         {
176                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
177         }
178
179         /* associate the domain SID with the (unique) handle. */
180         if (r_u.status == 0x0 && !set_lsa_policy_samr_sid(&(r_u.domain_pol), &(q_u->dom_sid.sid)))
181         {
182                 /* oh, whoops.  don't know what error message to return, here */
183                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
184         }
185
186         if (r_u.status != 0 && pol_open)
187         {
188                 close_lsa_policy_hnd(&(r_u.domain_pol));
189         }
190
191         DEBUG(5,("samr_open_domain: %d\n", __LINE__));
192
193         /* store the response in the SMB stream */
194         samr_io_r_open_domain("", &r_u, rdata, 0);
195
196         DEBUG(5,("samr_open_domain: %d\n", __LINE__));
197
198 }
199
200 /*******************************************************************
201  api_samr_open_domain
202  ********************************************************************/
203 static void api_samr_open_domain( uint16 vuid, prs_struct *data, prs_struct *rdata)
204 {
205         SAMR_Q_OPEN_DOMAIN q_u;
206         samr_io_q_open_domain("", &q_u, data, 0);
207         samr_reply_open_domain(&q_u, rdata);
208 }
209
210
211 /*******************************************************************
212  samr_reply_unknown_2c
213  ********************************************************************/
214 static void samr_reply_unknown_2c(SAMR_Q_UNKNOWN_2C *q_u,
215                                 prs_struct *rdata)
216 {
217         SAMR_R_UNKNOWN_2C r_u;
218         uint32 status = 0x0;
219
220         /* find the policy handle.  open a policy on it. */
221         if (status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->user_pol)) == -1))
222         {
223                 status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
224         }
225
226         /* find the user's rid */
227         if ((status == 0x0) && (get_lsa_policy_samr_rid(&(q_u->user_pol)) == 0xffffffff))
228         {
229                 status = 0xC0000000 | NT_STATUS_OBJECT_TYPE_MISMATCH;
230         }
231
232         make_samr_r_unknown_2c(&r_u, status);
233
234         DEBUG(5,("samr_unknown_2c: %d\n", __LINE__));
235
236         /* store the response in the SMB stream */
237         samr_io_r_unknown_2c("", &r_u, rdata, 0);
238
239         DEBUG(5,("samr_unknown_2c: %d\n", __LINE__));
240
241 }
242
243 /*******************************************************************
244  api_samr_unknown_2c
245  ********************************************************************/
246 static void api_samr_unknown_2c( uint16 vuid, prs_struct *data, prs_struct *rdata)
247 {
248         SAMR_Q_UNKNOWN_2C q_u;
249         samr_io_q_unknown_2c("", &q_u, data, 0);
250         samr_reply_unknown_2c(&q_u, rdata);
251 }
252
253
254 /*******************************************************************
255  samr_reply_unknown_3
256  ********************************************************************/
257 static void samr_reply_unknown_3(SAMR_Q_UNKNOWN_3 *q_u,
258                                 prs_struct *rdata)
259 {
260         SAMR_R_UNKNOWN_3 r_u;
261         DOM_SID3 sid[MAX_SAM_SIDS];
262         uint32 rid;
263         uint32 status;
264
265         status = 0x0;
266
267         /* find the policy handle.  open a policy on it. */
268         if (status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->user_pol)) == -1))
269         {
270                 status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
271         }
272
273         /* find the user's rid */
274         if (status == 0x0 && (rid = get_lsa_policy_samr_rid(&(q_u->user_pol))) == 0xffffffff)
275         {
276                 status = 0xC0000000 | NT_STATUS_OBJECT_TYPE_MISMATCH;
277         }
278
279         if (status == 0x0)
280         {
281                 DOM_SID usr_sid;
282
283                 usr_sid = global_sam_sid;
284
285                 SMB_ASSERT_ARRAY(usr_sid.sub_auths, usr_sid.num_auths+1);
286
287                 /*
288                  * Add the user RID.
289                  */
290                 sid_append_rid(&usr_sid, rid);
291                 
292                 /* maybe need another 1 or 2 (S-1-5-0x20-0x220 and S-1-5-20-0x224) */
293                 /* these two are DOMAIN_ADMIN and DOMAIN_ACCT_OP group RIDs */
294                 make_dom_sid3(&(sid[0]), 0x035b, 0x0002, &global_sid_S_1_1);
295                 make_dom_sid3(&(sid[1]), 0x0044, 0x0002, &usr_sid);
296         }
297
298         make_samr_r_unknown_3(&r_u,
299                                 0x0001, 0x8004,
300                                 0x00000014, 0x0002, 0x0070,
301                                 2, sid, status);
302
303         DEBUG(5,("samr_unknown_3: %d\n", __LINE__));
304
305         /* store the response in the SMB stream */
306         samr_io_r_unknown_3("", &r_u, rdata, 0);
307
308         DEBUG(5,("samr_unknown_3: %d\n", __LINE__));
309
310 }
311
312 /*******************************************************************
313  api_samr_unknown_3
314  ********************************************************************/
315 static void api_samr_unknown_3( uint16 vuid, prs_struct *data, prs_struct *rdata)
316 {
317         SAMR_Q_UNKNOWN_3 q_u;
318         samr_io_q_unknown_3("", &q_u, data, 0);
319         samr_reply_unknown_3(&q_u, rdata);
320 }
321
322
323 /*******************************************************************
324  samr_reply_enum_dom_users
325  ********************************************************************/
326 static void samr_reply_enum_dom_users(SAMR_Q_ENUM_DOM_USERS *q_u,
327                                 prs_struct *rdata)
328 {
329         SAMR_R_ENUM_DOM_USERS r_e;
330         SAM_USER_INFO_21 pass[MAX_SAM_ENTRIES];
331         int num_entries;
332         int total_entries;
333
334         r_e.status = 0x0;
335
336         /* find the policy handle.  open a policy on it. */
337         if (r_e.status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->pol)) == -1))
338         {
339                 r_e.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
340         }
341
342         DEBUG(5,("samr_reply_enum_dom_users: %d\n", __LINE__));
343
344         become_root(True);
345         get_sampwd_entries(pass, q_u->start_idx, &total_entries, &num_entries,
346                            MAX_SAM_ENTRIES, q_u->acb_mask);
347         unbecome_root(True);
348
349         make_samr_r_enum_dom_users(&r_e, 
350                                    q_u->start_idx + num_entries, num_entries,
351                                    pass, r_e.status);
352
353         /* store the response in the SMB stream */
354         samr_io_r_enum_dom_users("", &r_e, rdata, 0);
355
356         if (r_e.sam != NULL)
357         {
358                 free(r_e.sam);
359         }
360
361         if (r_e.uni_acct_name != NULL)
362         {
363                 free(r_e.uni_acct_name);
364         }
365
366         DEBUG(5,("samr_enum_dom_users: %d\n", __LINE__));
367
368 }
369
370 /*******************************************************************
371  api_samr_enum_dom_users
372  ********************************************************************/
373 static void api_samr_enum_dom_users( uint16 vuid, prs_struct *data, prs_struct *rdata)
374 {
375         SAMR_Q_ENUM_DOM_USERS q_e;
376         samr_io_q_enum_dom_users("", &q_e, data, 0);
377         samr_reply_enum_dom_users(&q_e, rdata);
378 }
379
380
381 /*******************************************************************
382  samr_reply_add_groupmem
383  ********************************************************************/
384 static void samr_reply_add_groupmem(SAMR_Q_ADD_GROUPMEM *q_u,
385                                 prs_struct *rdata)
386 {
387         SAMR_R_ADD_GROUPMEM r_e;
388         DOM_SID group_sid;
389         uint32 group_rid;
390         fstring group_sid_str;
391
392         r_e.status = 0x0;
393
394         /* find the policy handle.  open a policy on it. */
395         if (r_e.status == 0x0 && !get_lsa_policy_samr_sid(&q_u->pol, &group_sid))
396         {
397                 r_e.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
398         }
399         else
400         {
401                 sid_to_string(group_sid_str, &group_sid);
402                 sid_split_rid(&group_sid, &group_rid);
403         }
404
405         if (r_e.status == 0x0)
406         {
407                 DEBUG(10,("sid is %s\n", group_sid_str));
408
409                 if (sid_equal(&group_sid, &global_sam_sid))
410                 {
411                         DEBUG(10,("lookup on Domain SID\n"));
412
413                         become_root(True);
414                         r_e.status = add_group_member(group_rid, q_u->rid) ? 0x0 : (0xC0000000 | NT_STATUS_ACCESS_DENIED);
415                         unbecome_root(True);
416                 }
417                 else
418                 {
419                         r_e.status = 0xC0000000 | NT_STATUS_NO_SUCH_GROUP;
420                 }
421         }
422
423         /* store the response in the SMB stream */
424         samr_io_r_add_groupmem("", &r_e, rdata, 0);
425
426         DEBUG(5,("samr_add_groupmem: %d\n", __LINE__));
427 }
428
429 /*******************************************************************
430  api_samr_add_groupmem
431  ********************************************************************/
432 static void api_samr_add_groupmem( uint16 vuid, prs_struct *data, prs_struct *rdata)
433 {
434         SAMR_Q_ADD_GROUPMEM q_e;
435         samr_io_q_add_groupmem("", &q_e, data, 0);
436         samr_reply_add_groupmem(&q_e, rdata);
437 }
438
439 /*******************************************************************
440  samr_reply_del_groupmem
441  ********************************************************************/
442 static void samr_reply_del_groupmem(SAMR_Q_DEL_GROUPMEM *q_u,
443                                 prs_struct *rdata)
444 {
445         SAMR_R_DEL_GROUPMEM r_e;
446         DOM_SID group_sid;
447         uint32 group_rid;
448         fstring group_sid_str;
449
450         r_e.status = 0x0;
451
452         /* find the policy handle.  open a policy on it. */
453         if (r_e.status == 0x0 && !get_lsa_policy_samr_sid(&q_u->pol, &group_sid))
454         {
455                 r_e.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
456         }
457         else
458         {
459                 sid_to_string(group_sid_str, &group_sid);
460                 sid_split_rid(&group_sid, &group_rid);
461         }
462
463         if (r_e.status == 0x0)
464         {
465                 DEBUG(10,("sid is %s\n", group_sid_str));
466
467                 if (sid_equal(&group_sid, &global_sam_sid))
468                 {
469                         DEBUG(10,("lookup on Domain SID\n"));
470
471                         become_root(True);
472                         r_e.status = del_group_member(group_rid, q_u->rid) ? 0x0 : (0xC0000000 | NT_STATUS_ACCESS_DENIED);
473                         unbecome_root(True);
474                 }
475                 else
476                 {
477                         r_e.status = 0xC0000000 | NT_STATUS_NO_SUCH_GROUP;
478                 }
479         }
480
481         /* store the response in the SMB stream */
482         samr_io_r_del_groupmem("", &r_e, rdata, 0);
483
484         DEBUG(5,("samr_del_groupmem: %d\n", __LINE__));
485 }
486
487 /*******************************************************************
488  api_samr_del_groupmem
489  ********************************************************************/
490 static void api_samr_del_groupmem( uint16 vuid, prs_struct *data, prs_struct *rdata)
491 {
492         SAMR_Q_DEL_GROUPMEM q_e;
493         samr_io_q_del_groupmem("", &q_e, data, 0);
494         samr_reply_del_groupmem(&q_e, rdata);
495 }
496
497 /*******************************************************************
498  samr_reply_add_aliasmem
499  ********************************************************************/
500 static void samr_reply_add_aliasmem(SAMR_Q_ADD_ALIASMEM *q_u,
501                                 prs_struct *rdata)
502 {
503         SAMR_R_ADD_ALIASMEM r_e;
504         DOM_SID alias_sid;
505         uint32 alias_rid;
506         fstring alias_sid_str;
507
508         r_e.status = 0x0;
509
510         /* find the policy handle.  open a policy on it. */
511         if (r_e.status == 0x0 && !get_lsa_policy_samr_sid(&q_u->alias_pol, &alias_sid))
512         {
513                 r_e.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
514         }
515         else
516         {
517                 sid_to_string(alias_sid_str, &alias_sid);
518                 sid_split_rid(&alias_sid, &alias_rid);
519         }
520
521         if (r_e.status == 0x0)
522         {
523                 DEBUG(10,("sid is %s\n", alias_sid_str));
524
525                 if (sid_equal(&alias_sid, &global_sam_sid))
526                 {
527                         DEBUG(10,("add member on Domain SID\n"));
528
529                         become_root(True);
530                         r_e.status = add_alias_member(alias_rid, &q_u->sid.sid) ? 0x0 : (0xC0000000 | NT_STATUS_ACCESS_DENIED);
531                         unbecome_root(True);
532                 }
533                 else if (sid_equal(&alias_sid, &global_sid_S_1_5_20))
534                 {
535                         DEBUG(10,("add member on BUILTIN SID\n"));
536
537                         become_root(True);
538                         r_e.status = add_builtin_member(alias_rid, &q_u->sid.sid) ? 0x0 : (0xC0000000 | NT_STATUS_ACCESS_DENIED);
539                         unbecome_root(True);
540                 }
541                 else
542                 {
543                         r_e.status = 0xC0000000 | NT_STATUS_NO_SUCH_ALIAS;
544                 }
545         }
546
547         /* store the response in the SMB stream */
548         samr_io_r_add_aliasmem("", &r_e, rdata, 0);
549
550         DEBUG(5,("samr_add_aliasmem: %d\n", __LINE__));
551 }
552
553 /*******************************************************************
554  api_samr_add_aliasmem
555  ********************************************************************/
556 static void api_samr_add_aliasmem( uint16 vuid, prs_struct *data, prs_struct *rdata)
557 {
558         SAMR_Q_ADD_ALIASMEM q_e;
559         samr_io_q_add_aliasmem("", &q_e, data, 0);
560         samr_reply_add_aliasmem(&q_e, rdata);
561 }
562
563 /*******************************************************************
564  samr_reply_del_aliasmem
565  ********************************************************************/
566 static void samr_reply_del_aliasmem(SAMR_Q_DEL_ALIASMEM *q_u,
567                                 prs_struct *rdata)
568 {
569         SAMR_R_DEL_ALIASMEM r_e;
570         DOM_SID alias_sid;
571         uint32 alias_rid;
572         fstring alias_sid_str;
573
574         r_e.status = 0x0;
575
576         /* find the policy handle.  open a policy on it. */
577         if (r_e.status == 0x0 && !get_lsa_policy_samr_sid(&q_u->alias_pol, &alias_sid))
578         {
579                 r_e.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
580         }
581         else
582         {
583                 sid_to_string(alias_sid_str, &alias_sid);
584                 sid_split_rid(&alias_sid, &alias_rid);
585         }
586
587         if (r_e.status == 0x0)
588         {
589                 DEBUG(10,("sid is %s\n", alias_sid_str));
590
591                 if (sid_equal(&alias_sid, &global_sam_sid))
592                 {
593                         DEBUG(10,("del member on Domain SID\n"));
594
595                         become_root(True);
596                         r_e.status = del_alias_member(alias_rid, &q_u->sid.sid) ? 0x0 : (0xC0000000 | NT_STATUS_ACCESS_DENIED);
597                         unbecome_root(True);
598                 }
599                 else if (sid_equal(&alias_sid, &global_sid_S_1_5_20))
600                 {
601                         DEBUG(10,("del member on BUILTIN SID\n"));
602
603                         become_root(True);
604                         r_e.status = del_builtin_member(alias_rid, &q_u->sid.sid) ? 0x0 : (0xC0000000 | NT_STATUS_ACCESS_DENIED);
605                         unbecome_root(True);
606                 }
607                 else
608                 {
609                         r_e.status = 0xC0000000 | NT_STATUS_NO_SUCH_ALIAS;
610                 }
611         }
612
613         /* store the response in the SMB stream */
614         samr_io_r_del_aliasmem("", &r_e, rdata, 0);
615
616         DEBUG(5,("samr_del_aliasmem: %d\n", __LINE__));
617 }
618
619 /*******************************************************************
620  api_samr_del_aliasmem
621  ********************************************************************/
622 static void api_samr_del_aliasmem( uint16 vuid, prs_struct *data, prs_struct *rdata)
623 {
624         SAMR_Q_DEL_ALIASMEM q_e;
625         samr_io_q_del_aliasmem("", &q_e, data, 0);
626         samr_reply_del_aliasmem(&q_e, rdata);
627 }
628
629 /*******************************************************************
630  samr_reply_enum_dom_groups
631  ********************************************************************/
632 static void samr_reply_enum_dom_groups(SAMR_Q_ENUM_DOM_GROUPS *q_u,
633                                 prs_struct *rdata)
634 {
635         SAMR_R_ENUM_DOM_GROUPS r_e;
636         DOMAIN_GRP *grps = NULL;
637         int num_entries = 0;
638         DOM_SID sid;
639         fstring sid_str;
640
641         r_e.status = 0x0;
642         r_e.num_entries = 0;
643
644         /* find the policy handle.  open a policy on it. */
645         if (r_e.status == 0x0 && !get_lsa_policy_samr_sid(&q_u->pol, &sid))
646         {
647                 r_e.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
648         }
649
650         sid_to_string(sid_str, &sid);
651
652         DEBUG(5,("samr_reply_enum_dom_groups: sid %s\n", sid_str));
653
654         if (sid_equal(&sid, &global_sam_sid))
655         {
656                 BOOL ret;
657
658                 become_root(True);
659                 ret = enumdomgroups(&grps, &num_entries);
660                 unbecome_root(True);
661                 if (!ret)
662                 {
663                         r_e.status = 0xC0000000 | NT_STATUS_NO_MEMORY;
664                 }
665         }
666
667         if (r_e.status == 0x0)
668         {
669                 make_samr_r_enum_dom_groups(&r_e, num_entries, grps, r_e.status);
670         }
671
672         /* store the response in the SMB stream */
673         samr_io_r_enum_dom_groups("", &r_e, rdata, 0);
674
675         if (grps != NULL)
676         {
677                 free(grps);
678         }
679
680         DEBUG(5,("samr_enum_dom_groups: %d\n", __LINE__));
681 }
682
683 /*******************************************************************
684  api_samr_enum_dom_aliases
685  ********************************************************************/
686 static void api_samr_enum_dom_groups( uint16 vuid, prs_struct *data, prs_struct *rdata)
687 {
688         SAMR_Q_ENUM_DOM_GROUPS q_e;
689
690         /* grab the samr open */
691         samr_io_q_enum_dom_groups("", &q_e, data, 0);
692
693         /* construct reply. */
694         samr_reply_enum_dom_groups(&q_e, rdata);
695 }
696
697
698 /*******************************************************************
699  samr_reply_enum_dom_aliases
700  ********************************************************************/
701 static void samr_reply_enum_dom_aliases(SAMR_Q_ENUM_DOM_ALIASES *q_u,
702                                 prs_struct *rdata)
703 {
704         SAMR_R_ENUM_DOM_ALIASES r_e;
705         LOCAL_GRP *alss = NULL;
706         int num_entries = 0;
707         DOM_SID sid;
708         fstring sid_str;
709
710         r_e.status = 0x0;
711         r_e.num_entries = 0;
712
713         /* find the policy handle.  open a policy on it. */
714         if (r_e.status == 0x0 && !get_lsa_policy_samr_sid(&q_u->pol, &sid))
715         {
716                 r_e.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
717         }
718
719         sid_to_string(sid_str, &sid);
720
721         DEBUG(5,("samr_reply_enum_dom_aliases: sid %s\n", sid_str));
722
723         /* well-known aliases */
724         if (sid_equal(&sid, &global_sid_S_1_5_20))
725         {
726                 BOOL ret;
727                 /* builtin aliases */
728
729                 become_root(True);
730                 ret = enumdombuiltins(&alss, &num_entries);
731                 unbecome_root(True);
732                 if (!ret)
733                 {
734                         r_e.status = 0xC0000000 | NT_STATUS_NO_MEMORY;
735                 }
736         }
737         else if (sid_equal(&sid, &global_sam_sid))
738         {
739                 BOOL ret;
740                 /* local aliases */
741
742                 become_root(True);
743                 ret = enumdomaliases(&alss, &num_entries);
744                 unbecome_root(True);
745                 if (!ret)
746                 {
747                         r_e.status = 0xC0000000 | NT_STATUS_NO_MEMORY;
748                 }
749         }
750                 
751         if (r_e.status == 0x0)
752         {
753                 make_samr_r_enum_dom_aliases(&r_e, num_entries, alss, r_e.status);
754         }
755
756         /* store the response in the SMB stream */
757         samr_io_r_enum_dom_aliases("", &r_e, rdata, 0);
758
759         if (alss != NULL)
760         {
761                 free(alss);
762         }
763
764         DEBUG(5,("samr_enum_dom_aliases: %d\n", __LINE__));
765
766 }
767
768 /*******************************************************************
769  api_samr_enum_dom_aliases
770  ********************************************************************/
771 static void api_samr_enum_dom_aliases( uint16 vuid, prs_struct *data, prs_struct *rdata)
772 {
773         SAMR_Q_ENUM_DOM_ALIASES q_e;
774
775         /* grab the samr open */
776         samr_io_q_enum_dom_aliases("", &q_e, data, 0);
777
778         /* construct reply. */
779         samr_reply_enum_dom_aliases(&q_e, rdata);
780 }
781
782
783 /*******************************************************************
784  samr_reply_query_dispinfo
785  ********************************************************************/
786 static void samr_reply_query_dispinfo(SAMR_Q_QUERY_DISPINFO *q_u,
787                                 prs_struct *rdata)
788 {
789         SAMR_R_QUERY_DISPINFO r_e;
790         SAM_DISPINFO_CTR ctr;
791         SAM_USER_INFO_21 pass[MAX_SAM_ENTRIES];
792         DOMAIN_GRP *grps = NULL;
793         DOMAIN_GRP *sam_grps = NULL;
794         uint32 data_size = 0;
795         uint32 status = 0x0;
796         uint16 acb_mask = ACB_NORMAL;
797         int num_sam_entries = 0;
798         int num_entries = 0;
799         int total_entries;
800
801         DEBUG(5,("samr_reply_query_dispinfo: %d\n", __LINE__));
802
803         /* find the policy handle.  open a policy on it. */
804         if (find_lsa_policy_by_hnd(&(q_u->domain_pol)) == -1)
805         {
806                 status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
807                 DEBUG(5,("samr_reply_query_dispinfo: invalid handle\n"));
808         }
809
810         if (status == 0x0)
811         {
812                 become_root(True);
813
814                 /* Get what we need from the password database */
815                 switch (q_u->switch_level)
816                 {
817                         case 0x2:
818                         {
819                                 acb_mask = ACB_WSTRUST;
820                                 /* Fall through */
821                         }
822                         case 0x1:
823                         case 0x4:
824                         {
825                                 get_sampwd_entries(pass, q_u->start_idx,
826                                               &total_entries, &num_sam_entries,
827                                               MAX_SAM_ENTRIES, acb_mask);
828                                 break;
829                         }
830                         case 0x3:
831                         case 0x5:
832                         {
833                                 enumdomgroups(&sam_grps, &num_sam_entries);
834
835                                 if (q_u->start_idx < num_sam_entries) {
836                                         grps = sam_grps + q_u->start_idx;
837                                         num_sam_entries -= q_u->start_idx;
838                                 } else {
839                                         num_sam_entries = 0;
840                                 }
841                                 break;
842                         }
843                 }
844
845                 unbecome_root(True);
846
847                 num_entries = num_sam_entries;
848
849                 if (num_entries > q_u->max_entries)
850                 {
851                         num_entries = q_u->max_entries;
852                 }
853
854                 if (num_entries > MAX_SAM_ENTRIES)
855                 {
856                         num_entries = MAX_SAM_ENTRIES;
857                         DEBUG(5,("limiting number of entries to %d\n", 
858                                  num_entries));
859                 }
860
861                 data_size = q_u->max_size;
862
863                 /* Now create reply structure */
864                 switch (q_u->switch_level)
865                 {
866                         case 0x1:
867                         {
868                                 ctr.sam.info1 = malloc(sizeof(SAM_DISPINFO_1));
869                                 make_sam_dispinfo_1(ctr.sam.info1,
870                                                     &num_entries, &data_size,
871                                                     q_u->start_idx, pass);
872                                 break;
873                         }
874                         case 0x2:
875                         {
876                                 ctr.sam.info2 = malloc(sizeof(SAM_DISPINFO_2));
877                                 make_sam_dispinfo_2(ctr.sam.info2,
878                                                     &num_entries, &data_size,
879                                                     q_u->start_idx, pass);
880                                 break;
881                         }
882                         case 0x3:
883                         {
884                                 ctr.sam.info3 = malloc(sizeof(SAM_DISPINFO_3));
885                                 make_sam_dispinfo_3(ctr.sam.info3,
886                                                     &num_entries, &data_size,
887                                                     q_u->start_idx, grps);
888                                 break;
889                         }
890                         case 0x4:
891                         {
892                                 ctr.sam.info4 = malloc(sizeof(SAM_DISPINFO_4));
893                                 make_sam_dispinfo_4(ctr.sam.info4,
894                                                     &num_entries, &data_size,
895                                                     q_u->start_idx, pass);
896                                 break;
897                         }
898                         case 0x5:
899                         {
900                                 ctr.sam.info5 = malloc(sizeof(SAM_DISPINFO_5));
901                                 make_sam_dispinfo_5(ctr.sam.info5,
902                                                     &num_entries, &data_size,
903                                                     q_u->start_idx, grps);
904                                 break;
905                         }
906                         default:
907                         {
908                                 ctr.sam.info = NULL;
909                                 status = 0xC0000000 | NT_STATUS_INVALID_INFO_CLASS;
910                                 break;
911                         }
912                 }
913         }
914
915         if ((status == 0) && (num_entries < num_sam_entries))
916         {
917                 status = NT_STATUS_MORE_ENTRIES;
918         }
919
920         make_samr_r_query_dispinfo(&r_e, num_entries, data_size,
921                                    q_u->switch_level, &ctr, status);
922
923         /* store the response in the SMB stream */
924         samr_io_r_query_dispinfo("", &r_e, rdata, 0);
925
926         /* free malloc'd areas */
927         if (sam_grps != NULL)
928         {
929                 free(sam_grps);
930         }
931
932         if (ctr.sam.info != NULL)
933         {
934                 free(ctr.sam.info);
935         }
936
937         DEBUG(5,("samr_reply_query_dispinfo: %d\n", __LINE__));
938 }
939
940 /*******************************************************************
941  api_samr_query_dispinfo
942  ********************************************************************/
943 static void api_samr_query_dispinfo( uint16 vuid, prs_struct *data, prs_struct *rdata)
944 {
945         SAMR_Q_QUERY_DISPINFO q_e;
946
947         samr_io_q_query_dispinfo("", &q_e, data, 0);
948         samr_reply_query_dispinfo(&q_e, rdata);
949 }
950
951 /*******************************************************************
952  samr_reply_delete_dom_group
953  ********************************************************************/
954 static void samr_reply_delete_dom_group(SAMR_Q_DELETE_DOM_GROUP *q_u,
955                                 prs_struct *rdata)
956 {
957         uint32 status = 0;
958
959         DOM_SID group_sid;
960         uint32 group_rid;
961         fstring group_sid_str;
962
963         SAMR_R_DELETE_DOM_GROUP r_u;
964
965         DEBUG(5,("samr_delete_dom_group: %d\n", __LINE__));
966
967         /* find the policy handle.  open a policy on it. */
968         if (status == 0x0 && !get_lsa_policy_samr_sid(&q_u->group_pol, &group_sid))
969         {
970                 status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
971         }
972         else
973         {
974                 sid_to_string(group_sid_str, &group_sid     );
975                 sid_split_rid(&group_sid, &group_rid);
976         }
977
978         if (status == 0x0)
979         {
980                 DEBUG(10,("sid is %s\n", group_sid_str));
981
982                 if (sid_equal(&group_sid, &global_sam_sid))
983                 {
984                         DEBUG(10,("lookup on Domain SID\n"));
985
986                         become_root(True);
987                         status = del_group_entry(group_rid) ? 0x0 : (0xC0000000 | NT_STATUS_NO_SUCH_GROUP);
988                         unbecome_root(True);
989                 }
990                 else
991                 {
992                         status = 0xC0000000 | NT_STATUS_NO_SUCH_GROUP;
993                 }
994         }
995
996         make_samr_r_delete_dom_group(&r_u, status);
997
998         /* store the response in the SMB stream */
999         samr_io_r_delete_dom_group("", &r_u, rdata, 0);
1000 }
1001
1002 /*******************************************************************
1003  api_samr_delete_dom_group
1004  ********************************************************************/
1005 static void api_samr_delete_dom_group( uint16 vuid, prs_struct *data, prs_struct *rdata)
1006 {
1007         SAMR_Q_DELETE_DOM_GROUP q_u;
1008         samr_io_q_delete_dom_group("", &q_u, data, 0);
1009         samr_reply_delete_dom_group(&q_u, rdata);
1010 }
1011
1012
1013 /*******************************************************************
1014  samr_reply_query_groupmem
1015  ********************************************************************/
1016 static void samr_reply_query_groupmem(SAMR_Q_QUERY_GROUPMEM *q_u,
1017                                 prs_struct *rdata)
1018 {
1019         uint32 status = 0;
1020
1021         DOMAIN_GRP_MEMBER *mem_grp = NULL;
1022         uint32 *rid = NULL;
1023         uint32 *attr = NULL;
1024         int num_rids = 0;
1025         DOM_SID group_sid;
1026         uint32 group_rid;
1027         fstring group_sid_str;
1028
1029         SAMR_R_QUERY_GROUPMEM r_u;
1030
1031         DEBUG(5,("samr_query_groupmem: %d\n", __LINE__));
1032
1033         /* find the policy handle.  open a policy on it. */
1034         if (status == 0x0 && !get_lsa_policy_samr_sid(&q_u->group_pol, &group_sid))
1035         {
1036                 status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
1037         }
1038         else
1039         {
1040                 sid_to_string(group_sid_str, &group_sid     );
1041                 sid_split_rid(&group_sid, &group_rid);
1042         }
1043
1044         if (status == 0x0)
1045         {
1046                 DEBUG(10,("sid is %s\n", group_sid_str));
1047
1048                 if (sid_equal(&group_sid, &global_sam_sid))
1049                 {
1050                         DEBUG(10,("lookup on Domain SID\n"));
1051
1052                         become_root(True);
1053                         status = getgrouprid(group_rid, &mem_grp, &num_rids) != NULL ? 0x0 : (0xC0000000 | NT_STATUS_NO_SUCH_GROUP);
1054                         unbecome_root(True);
1055                 }
1056                 else
1057                 {
1058                         status = 0xC0000000 | NT_STATUS_NO_SUCH_GROUP;
1059                 }
1060         }
1061
1062         if (status == 0x0 && num_rids > 0)
1063         {
1064                 rid  = malloc(num_rids * sizeof(uint32));
1065                 attr = malloc(num_rids * sizeof(uint32));
1066                 if (mem_grp != NULL && rid != NULL && attr != NULL)
1067                 {
1068                         int i;
1069                         for (i = 0; i < num_rids; i++)
1070                         {
1071                                 rid [i] = mem_grp[i].rid;
1072                                 attr[i] = mem_grp[i].attr;
1073                         }
1074                         free(mem_grp);
1075                 }
1076         }
1077
1078         make_samr_r_query_groupmem(&r_u, num_rids, rid, attr, status);
1079
1080         /* store the response in the SMB stream */
1081         samr_io_r_query_groupmem("", &r_u, rdata, 0);
1082
1083         if (rid != NULL)
1084         {
1085                 free(rid);
1086         }
1087
1088         if (attr != NULL)
1089         {
1090                 free(attr);
1091         }
1092
1093         DEBUG(5,("samr_query_groupmem: %d\n", __LINE__));
1094
1095 }
1096
1097 /*******************************************************************
1098  api_samr_query_groupmem
1099  ********************************************************************/
1100 static void api_samr_query_groupmem( uint16 vuid, prs_struct *data, prs_struct *rdata)
1101 {
1102         SAMR_Q_QUERY_GROUPMEM q_u;
1103         samr_io_q_query_groupmem("", &q_u, data, 0);
1104         samr_reply_query_groupmem(&q_u, rdata);
1105 }
1106
1107
1108 /*******************************************************************
1109  samr_reply_query_groupinfo
1110  ********************************************************************/
1111 static void samr_reply_query_groupinfo(SAMR_Q_QUERY_GROUPINFO *q_u,
1112                                 prs_struct *rdata)
1113 {
1114         SAMR_R_QUERY_GROUPINFO r_e;
1115         GROUP_INFO_CTR ctr;
1116         uint32 status = 0x0;
1117
1118         r_e.ptr = 0;
1119
1120         /* find the policy handle.  open a policy on it. */
1121         if (r_e.status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->pol)) == -1))
1122         {
1123                 r_e.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
1124         }
1125
1126         DEBUG(5,("samr_reply_query_groupinfo: %d\n", __LINE__));
1127
1128         if (status == 0x0)
1129         {
1130                 if (q_u->switch_level == 1)
1131                 {
1132                         r_e.ptr = 1;
1133                         ctr.switch_value1 = 1;
1134                         make_samr_group_info1(&ctr.group.info1, "account name", "account description");
1135                 }
1136                 else if (q_u->switch_level == 4)
1137                 {
1138                         r_e.ptr = 1;
1139                         ctr.switch_value1 = 4;
1140                         make_samr_group_info4(&ctr.group.info4, "account description");
1141                 }
1142                 else
1143                 {
1144                         status = 0xC0000000 | NT_STATUS_INVALID_INFO_CLASS;
1145                 }
1146         }
1147
1148         make_samr_r_query_groupinfo(&r_e, status == 0 ? &ctr : NULL, status);
1149
1150         /* store the response in the SMB stream */
1151         samr_io_r_query_groupinfo("", &r_e, rdata, 0);
1152
1153         DEBUG(5,("samr_query_groupinfo: %d\n", __LINE__));
1154
1155 }
1156
1157 /*******************************************************************
1158  api_samr_query_groupinfo
1159  ********************************************************************/
1160 static void api_samr_query_groupinfo( uint16 vuid, prs_struct *data, prs_struct *rdata)
1161 {
1162         SAMR_Q_QUERY_GROUPINFO q_e;
1163         samr_io_q_query_groupinfo("", &q_e, data, 0);
1164         samr_reply_query_groupinfo(&q_e, rdata);
1165 }
1166
1167
1168 /*******************************************************************
1169  samr_reply_query_aliasinfo
1170  ********************************************************************/
1171 static void samr_reply_query_aliasinfo(SAMR_Q_QUERY_ALIASINFO *q_u,
1172                                 prs_struct *rdata)
1173 {
1174         SAMR_R_QUERY_ALIASINFO r_e;
1175         ALIAS_INFO_CTR ctr;
1176         uint32 status = 0x0;
1177
1178         r_e.ptr = 0;
1179
1180         /* find the policy handle.  open a policy on it. */
1181         if (r_e.status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->pol)) == -1))
1182         {
1183                 r_e.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
1184         }
1185
1186         DEBUG(5,("samr_reply_query_aliasinfo: %d\n", __LINE__));
1187
1188         if (status == 0x0)
1189         {
1190                 if (q_u->switch_level == 3)
1191                 {
1192                         r_e.ptr = 1;
1193                         ctr.switch_value1 = 3;
1194                         make_samr_alias_info3(&ctr.alias.info3, "<account description>");
1195                 }
1196                 else
1197                 {
1198                         status = 0xC0000000 | NT_STATUS_INVALID_INFO_CLASS;
1199                 }
1200         }
1201
1202         make_samr_r_query_aliasinfo(&r_e, status == 0 ? &ctr : NULL, status);
1203
1204         /* store the response in the SMB stream */
1205         samr_io_r_query_aliasinfo("", &r_e, rdata, 0);
1206
1207         DEBUG(5,("samr_query_aliasinfo: %d\n", __LINE__));
1208
1209 }
1210
1211 /*******************************************************************
1212  api_samr_query_aliasinfo
1213  ********************************************************************/
1214 static void api_samr_query_aliasinfo( uint16 vuid, prs_struct *data, prs_struct *rdata)
1215 {
1216         SAMR_Q_QUERY_ALIASINFO q_e;
1217         samr_io_q_query_aliasinfo("", &q_e, data, 0);
1218         samr_reply_query_aliasinfo(&q_e, rdata);
1219 }
1220
1221
1222 /*******************************************************************
1223  samr_reply_query_useraliases
1224  ********************************************************************/
1225 static void samr_reply_query_useraliases(SAMR_Q_QUERY_USERALIASES *q_u,
1226                                 prs_struct *rdata)
1227 {
1228         uint32 status = 0;
1229
1230         LOCAL_GRP *mem_grp = NULL;
1231         uint32 *rid = NULL;
1232         int num_rids = 0;
1233         struct sam_passwd *sam_pass;
1234         DOM_SID usr_sid;
1235         DOM_SID dom_sid;
1236         uint32 user_rid;
1237         fstring sam_sid_str;
1238         fstring dom_sid_str;
1239         fstring usr_sid_str;
1240
1241         SAMR_R_QUERY_USERALIASES r_u;
1242
1243         DEBUG(5,("samr_query_useraliases: %d\n", __LINE__));
1244
1245         /* find the policy handle.  open a policy on it. */
1246         if (status == 0x0 && !get_lsa_policy_samr_sid(&q_u->pol, &dom_sid))
1247         {
1248                 status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
1249         }
1250         else
1251         {
1252                 sid_to_string(dom_sid_str, &dom_sid       );
1253                 sid_to_string(sam_sid_str, &global_sam_sid);
1254         }
1255
1256         if (status == 0x0)
1257         {
1258                 usr_sid = q_u->sid[0].sid;
1259                 sid_split_rid(&usr_sid, &user_rid);
1260                 sid_to_string(usr_sid_str, &usr_sid);
1261
1262         }
1263
1264         if (status == 0x0)
1265         {
1266                 /* find the user account */
1267                 become_root(True);
1268                 sam_pass = getsam21pwrid(user_rid);
1269                 unbecome_root(True);
1270
1271                 if (sam_pass == NULL)
1272                 {
1273                         status = 0xC0000000 | NT_STATUS_NO_SUCH_USER;
1274                         num_rids = 0;
1275                 }
1276         }
1277
1278         if (status == 0x0)
1279         {
1280                 DEBUG(10,("sid is %s\n", dom_sid_str));
1281
1282                 if (sid_equal(&dom_sid, &global_sid_S_1_5_20))
1283                 {
1284                         DEBUG(10,("lookup on S-1-5-20\n"));
1285
1286                         become_root(True);
1287                         getuserbuiltinntnam(sam_pass->nt_name, &mem_grp, &num_rids);
1288                         unbecome_root(True);
1289                 }
1290                 else if (sid_equal(&dom_sid, &usr_sid))
1291                 {
1292                         DEBUG(10,("lookup on Domain SID\n"));
1293
1294                         become_root(True);
1295                         getuseraliasntnam(sam_pass->nt_name, &mem_grp, &num_rids);
1296                         unbecome_root(True);
1297                 }
1298                 else
1299                 {
1300                         status = 0xC0000000 | NT_STATUS_NO_SUCH_USER;
1301                 }
1302         }
1303
1304         if (status == 0x0 && num_rids > 0)
1305         {
1306                 rid = malloc(num_rids * sizeof(uint32));
1307                 if (mem_grp != NULL && rid != NULL)
1308                 {
1309                         int i;
1310                         for (i = 0; i < num_rids; i++)
1311                         {
1312                                 rid[i] = mem_grp[i].rid;
1313                         }
1314                         free(mem_grp);
1315                 }
1316         }
1317
1318         make_samr_r_query_useraliases(&r_u, num_rids, rid, status);
1319
1320         /* store the response in the SMB stream */
1321         samr_io_r_query_useraliases("", &r_u, rdata, 0);
1322
1323         if (rid != NULL)
1324         {
1325                 free(rid);
1326         }
1327
1328         DEBUG(5,("samr_query_useraliases: %d\n", __LINE__));
1329
1330 }
1331
1332 /*******************************************************************
1333  api_samr_query_useraliases
1334  ********************************************************************/
1335 static void api_samr_query_useraliases( uint16 vuid, prs_struct *data, prs_struct *rdata)
1336 {
1337         SAMR_Q_QUERY_USERALIASES q_u;
1338         samr_io_q_query_useraliases("", &q_u, data, 0);
1339         samr_reply_query_useraliases(&q_u, rdata);
1340 }
1341
1342 /*******************************************************************
1343  samr_reply_delete_dom_alias
1344  ********************************************************************/
1345 static void samr_reply_delete_dom_alias(SAMR_Q_DELETE_DOM_ALIAS *q_u,
1346                                 prs_struct *rdata)
1347 {
1348         uint32 status = 0;
1349
1350         DOM_SID alias_sid;
1351         uint32 alias_rid;
1352         fstring alias_sid_str;
1353
1354         SAMR_R_DELETE_DOM_ALIAS r_u;
1355
1356         DEBUG(5,("samr_delete_dom_alias: %d\n", __LINE__));
1357
1358         /* find the policy handle.  open a policy on it. */
1359         if (status == 0x0 && !get_lsa_policy_samr_sid(&q_u->alias_pol, &alias_sid))
1360         {
1361                 status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
1362         }
1363         else
1364         {
1365                 sid_to_string(alias_sid_str, &alias_sid     );
1366                 sid_split_rid(&alias_sid, &alias_rid);
1367         }
1368
1369         if (status == 0x0)
1370         {
1371                 DEBUG(10,("sid is %s\n", alias_sid_str));
1372
1373                 if (sid_equal(&alias_sid, &global_sam_sid))
1374                 {
1375                         DEBUG(10,("lookup on Domain SID\n"));
1376
1377                         become_root(True);
1378                         status = del_alias_entry(alias_rid) ? 0x0 : (0xC0000000 | NT_STATUS_NO_SUCH_ALIAS);
1379                         unbecome_root(True);
1380                 }
1381                 else
1382                 {
1383                         status = 0xC0000000 | NT_STATUS_NO_SUCH_ALIAS;
1384                 }
1385         }
1386
1387         make_samr_r_delete_dom_alias(&r_u, status);
1388
1389         /* store the response in the SMB stream */
1390         samr_io_r_delete_dom_alias("", &r_u, rdata, 0);
1391 }
1392
1393 /*******************************************************************
1394  api_samr_delete_dom_alias
1395  ********************************************************************/
1396 static void api_samr_delete_dom_alias( uint16 vuid, prs_struct *data, prs_struct *rdata)
1397 {
1398         SAMR_Q_DELETE_DOM_ALIAS q_u;
1399         samr_io_q_delete_dom_alias("", &q_u, data, 0);
1400         samr_reply_delete_dom_alias(&q_u, rdata);
1401 }
1402
1403
1404 /*******************************************************************
1405  samr_reply_query_aliasmem
1406  ********************************************************************/
1407 static void samr_reply_query_aliasmem(SAMR_Q_QUERY_ALIASMEM *q_u,
1408                                 prs_struct *rdata)
1409 {
1410         uint32 status = 0;
1411
1412         LOCAL_GRP_MEMBER *mem_grp = NULL;
1413         DOM_SID2 *sid = NULL;
1414         int num_sids = 0;
1415         DOM_SID alias_sid;
1416         uint32 alias_rid;
1417         fstring alias_sid_str;
1418
1419         SAMR_R_QUERY_ALIASMEM r_u;
1420
1421         DEBUG(5,("samr_query_aliasmem: %d\n", __LINE__));
1422
1423         /* find the policy handle.  open a policy on it. */
1424         if (status == 0x0 && !get_lsa_policy_samr_sid(&q_u->alias_pol, &alias_sid))
1425         {
1426                 status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
1427         }
1428         else
1429         {
1430                 sid_to_string(alias_sid_str, &alias_sid     );
1431                 sid_split_rid(&alias_sid, &alias_rid);
1432         }
1433
1434         if (status == 0x0)
1435         {
1436                 DEBUG(10,("sid is %s\n", alias_sid_str));
1437
1438                 if (sid_equal(&alias_sid, &global_sid_S_1_5_20))
1439                 {
1440                         DEBUG(10,("lookup on S-1-5-20\n"));
1441
1442                         become_root(True);
1443                         status = getbuiltinrid(alias_rid, &mem_grp, &num_sids) != NULL ? 0x0 : 0xC0000000 | NT_STATUS_NO_SUCH_ALIAS;
1444                         unbecome_root(True);
1445                 }
1446                 else if (sid_equal(&alias_sid, &global_sam_sid))
1447                 {
1448                         DEBUG(10,("lookup on Domain SID\n"));
1449
1450                         become_root(True);
1451                         status = getaliasrid(alias_rid, &mem_grp, &num_sids) != NULL ? 0x0 : 0xC0000000 | NT_STATUS_NO_SUCH_ALIAS;
1452                         unbecome_root(True);
1453                 }
1454                 else
1455                 {
1456                         status = 0xC0000000 | NT_STATUS_NO_SUCH_ALIAS;
1457                 }
1458         }
1459
1460         if (status == 0x0 && num_sids > 0)
1461         {
1462                 sid = malloc(num_sids * sizeof(DOM_SID));
1463                 if (mem_grp != NULL && sid != NULL)
1464                 {
1465                         int i;
1466                         for (i = 0; i < num_sids; i++)
1467                         {
1468                                 make_dom_sid2(&sid[i], &mem_grp[i].sid);
1469                         }
1470                         free(mem_grp);
1471                 }
1472         }
1473
1474         make_samr_r_query_aliasmem(&r_u, num_sids, sid, status);
1475
1476         /* store the response in the SMB stream */
1477         samr_io_r_query_aliasmem("", &r_u, rdata, 0);
1478
1479         if (sid != NULL)
1480         {
1481                 free(sid);
1482         }
1483
1484         DEBUG(5,("samr_query_aliasmem: %d\n", __LINE__));
1485
1486 }
1487
1488 /*******************************************************************
1489  api_samr_query_aliasmem
1490  ********************************************************************/
1491 static void api_samr_query_aliasmem( uint16 vuid, prs_struct *data, prs_struct *rdata)
1492 {
1493         SAMR_Q_QUERY_ALIASMEM q_u;
1494         samr_io_q_query_aliasmem("", &q_u, data, 0);
1495         samr_reply_query_aliasmem(&q_u, rdata);
1496 }
1497
1498 /*******************************************************************
1499  samr_reply_lookup_names
1500  ********************************************************************/
1501 static void samr_reply_lookup_names(SAMR_Q_LOOKUP_NAMES *q_u,
1502                                 prs_struct *rdata)
1503 {
1504         uint32 rid [MAX_SAM_ENTRIES];
1505         uint8  type[MAX_SAM_ENTRIES];
1506         uint32 status     = 0;
1507         int i;
1508         int num_rids = q_u->num_names1;
1509         DOM_SID pol_sid;
1510
1511         SAMR_R_LOOKUP_NAMES r_u;
1512
1513         DEBUG(5,("samr_lookup_names: %d\n", __LINE__));
1514
1515         if (status == 0x0 && !get_lsa_policy_samr_sid(&q_u->pol, &pol_sid))
1516         {
1517                 status = 0xC0000000 | NT_STATUS_OBJECT_TYPE_MISMATCH;
1518         }
1519
1520         if (num_rids > MAX_SAM_ENTRIES)
1521         {
1522                 num_rids = MAX_SAM_ENTRIES;
1523                 DEBUG(5,("samr_lookup_names: truncating entries to %d\n", num_rids));
1524         }
1525
1526         SMB_ASSERT_ARRAY(q_u->uni_name, num_rids);
1527
1528         for (i = 0; i < num_rids && status == 0; i++)
1529         {
1530                 DOM_SID sid;
1531                 fstring name;
1532                 unistr2_to_ascii(name, &q_u->uni_name[i], sizeof(name)-1);
1533
1534                 status = lookup_name(name, &sid, &(type[i]));
1535                 if (status == 0x0)
1536                 {
1537                         sid_split_rid(&sid, &rid[i]);
1538                 }
1539                 else
1540                 {
1541                         type[i] = SID_NAME_UNKNOWN;
1542                         rid [i] = 0xffffffff;
1543                 }
1544                 if (!sid_equal(&pol_sid, &sid))
1545                 {
1546                         rid [i] = 0xffffffff;
1547                         type[i] = SID_NAME_UNKNOWN;
1548                 }
1549         }
1550
1551         make_samr_r_lookup_names(&r_u, num_rids, rid, type, status);
1552
1553         /* store the response in the SMB stream */
1554         samr_io_r_lookup_names("", &r_u, rdata, 0);
1555
1556         DEBUG(5,("samr_lookup_names: %d\n", __LINE__));
1557
1558 }
1559
1560 /*******************************************************************
1561  api_samr_lookup_names
1562  ********************************************************************/
1563 static void api_samr_lookup_names( uint16 vuid, prs_struct *data, prs_struct *rdata)
1564 {
1565         SAMR_Q_LOOKUP_NAMES q_u;
1566         samr_io_q_lookup_names("", &q_u, data, 0);
1567         samr_reply_lookup_names(&q_u, rdata);
1568 }
1569
1570 /*******************************************************************
1571  samr_reply_chgpasswd_user
1572  ********************************************************************/
1573 static void samr_reply_chgpasswd_user(SAMR_Q_CHGPASSWD_USER *q_u,
1574                                 prs_struct *rdata)
1575 {
1576         SAMR_R_CHGPASSWD_USER r_u;
1577         uint32 status = 0x0;
1578         fstring user_name;
1579         fstring wks;
1580
1581         unistr2_to_ascii(user_name, &q_u->uni_user_name, sizeof(user_name)-1);
1582         unistr2_to_ascii(wks, &q_u->uni_dest_host, sizeof(wks)-1);
1583
1584         DEBUG(5,("samr_chgpasswd_user: user: %s wks: %s\n", user_name, wks));
1585
1586         if (!pass_oem_change(user_name,
1587                              q_u->lm_newpass.pass, q_u->lm_oldhash.hash,
1588                              q_u->nt_newpass.pass, q_u->nt_oldhash.hash))
1589         {
1590                 status = 0xC0000000 | NT_STATUS_WRONG_PASSWORD;
1591         }
1592
1593         make_samr_r_chgpasswd_user(&r_u, status);
1594
1595         /* store the response in the SMB stream */
1596         samr_io_r_chgpasswd_user("", &r_u, rdata, 0);
1597
1598         DEBUG(5,("samr_chgpasswd_user: %d\n", __LINE__));
1599 }
1600
1601 /*******************************************************************
1602  api_samr_chgpasswd_user
1603  ********************************************************************/
1604 static void api_samr_chgpasswd_user( uint16 vuid, prs_struct *data, prs_struct *rdata)
1605 {
1606         SAMR_Q_CHGPASSWD_USER q_u;
1607         samr_io_q_chgpasswd_user("", &q_u, data, 0);
1608         samr_reply_chgpasswd_user(&q_u, rdata);
1609 }
1610
1611
1612 /*******************************************************************
1613  samr_reply_unknown_38
1614  ********************************************************************/
1615 static void samr_reply_unknown_38(SAMR_Q_UNKNOWN_38 *q_u,
1616                                 prs_struct *rdata)
1617 {
1618         SAMR_R_UNKNOWN_38 r_u;
1619
1620         DEBUG(5,("samr_unknown_38: %d\n", __LINE__));
1621
1622         make_samr_r_unknown_38(&r_u);
1623
1624         /* store the response in the SMB stream */
1625         samr_io_r_unknown_38("", &r_u, rdata, 0);
1626
1627         DEBUG(5,("samr_unknown_38: %d\n", __LINE__));
1628 }
1629
1630 /*******************************************************************
1631  api_samr_unknown_38
1632  ********************************************************************/
1633 static void api_samr_unknown_38( uint16 vuid, prs_struct *data, prs_struct *rdata)
1634 {
1635         SAMR_Q_UNKNOWN_38 q_u;
1636         samr_io_q_unknown_38("", &q_u, data, 0);
1637         samr_reply_unknown_38(&q_u, rdata);
1638 }
1639
1640
1641 /*******************************************************************
1642  samr_reply_lookup_rids
1643  ********************************************************************/
1644 static void samr_reply_lookup_rids(SAMR_Q_LOOKUP_RIDS *q_u,
1645                                 prs_struct *rdata)
1646 {
1647         fstring group_names[MAX_SAM_ENTRIES];
1648         uint8   group_attrs[MAX_SAM_ENTRIES];
1649         uint32 status     = 0;
1650         int num_rids = q_u->num_rids1;
1651         DOM_SID pol_sid;
1652
1653         SAMR_R_LOOKUP_RIDS r_u;
1654
1655         DEBUG(5,("samr_lookup_rids: %d\n", __LINE__));
1656
1657         /* find the policy handle.  open a policy on it. */
1658         if (status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->pol)) == -1))
1659         {
1660                 status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
1661         }
1662
1663         if (status == 0x0 && !get_lsa_policy_samr_sid(&q_u->pol, &pol_sid))
1664         {
1665                 status = 0xC0000000 | NT_STATUS_OBJECT_TYPE_MISMATCH;
1666         }
1667
1668         if (status == 0x0)
1669         {
1670                 int i;
1671                 if (num_rids > MAX_SAM_ENTRIES)
1672                 {
1673                         num_rids = MAX_SAM_ENTRIES;
1674                         DEBUG(5,("samr_lookup_rids: truncating entries to %d\n", num_rids));
1675                 }
1676
1677                 for (i = 0; i < num_rids && status == 0; i++)
1678                 {
1679                         DOM_SID sid;
1680                         sid_copy(&sid, &pol_sid);
1681                         sid_append_rid(&sid, q_u->rid[i]);
1682                         lookup_sid(&sid, group_names[i], &group_attrs[i]);
1683                 }
1684         }
1685
1686         make_samr_r_lookup_rids(&r_u, num_rids, group_names, group_attrs, status);
1687
1688         /* store the response in the SMB stream */
1689         samr_io_r_lookup_rids("", &r_u, rdata, 0);
1690
1691         DEBUG(5,("samr_lookup_rids: %d\n", __LINE__));
1692
1693 }
1694
1695 /*******************************************************************
1696  api_samr_lookup_rids
1697  ********************************************************************/
1698 static void api_samr_lookup_rids( uint16 vuid, prs_struct *data, prs_struct *rdata)
1699 {
1700         SAMR_Q_LOOKUP_RIDS q_u;
1701         samr_io_q_lookup_rids("", &q_u, data, 0);
1702         samr_reply_lookup_rids(&q_u, rdata);
1703 }
1704
1705
1706 /*******************************************************************
1707  samr_reply_open_user
1708  ********************************************************************/
1709 static void samr_reply_open_user(SAMR_Q_OPEN_USER *q_u,
1710                                 prs_struct *rdata,
1711                                 int status)
1712 {
1713         SAMR_R_OPEN_USER r_u;
1714         struct sam_passwd *sam_pass;
1715         BOOL pol_open = False;
1716
1717         /* set up the SAMR open_user response */
1718         bzero(r_u.user_pol.data, POL_HND_SIZE);
1719
1720         r_u.status = 0x0;
1721
1722         /* find the policy handle.  open a policy on it. */
1723         if (r_u.status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->domain_pol)) == -1))
1724         {
1725                 r_u.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
1726         }
1727
1728         /* get a (unique) handle.  open a policy on it. */
1729         if (r_u.status == 0x0 && !(pol_open = open_lsa_policy_hnd(&(r_u.user_pol))))
1730         {
1731                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
1732         }
1733
1734         become_root(True);
1735         sam_pass = getsam21pwrid(q_u->user_rid);
1736         unbecome_root(True);
1737
1738         /* check that the RID exists in our domain. */
1739         if (r_u.status == 0x0 && sam_pass == NULL)
1740         {
1741                 r_u.status = 0xC0000000 | NT_STATUS_NO_SUCH_USER;
1742         }
1743
1744         /* associate the RID with the (unique) handle. */
1745         if (r_u.status == 0x0 && !set_lsa_policy_samr_rid(&(r_u.user_pol), q_u->user_rid))
1746         {
1747                 /* oh, whoops.  don't know what error message to return, here */
1748                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
1749         }
1750
1751         if (r_u.status != 0 && pol_open)
1752         {
1753                 close_lsa_policy_hnd(&(r_u.user_pol));
1754         }
1755
1756         DEBUG(5,("samr_open_user: %d\n", __LINE__));
1757
1758         /* store the response in the SMB stream */
1759         samr_io_r_open_user("", &r_u, rdata, 0);
1760
1761         DEBUG(5,("samr_open_user: %d\n", __LINE__));
1762
1763 }
1764
1765 /*******************************************************************
1766  api_samr_open_user
1767  ********************************************************************/
1768 static void api_samr_open_user( uint16 vuid, prs_struct *data, prs_struct *rdata)
1769 {
1770         SAMR_Q_OPEN_USER q_u;
1771         samr_io_q_open_user("", &q_u, data, 0);
1772         samr_reply_open_user(&q_u, rdata, 0x0);
1773 }
1774
1775
1776 /*************************************************************************
1777  get_user_info_10
1778  *************************************************************************/
1779 static BOOL get_user_info_10(SAM_USER_INFO_10 *id10, uint32 user_rid)
1780 {
1781         struct sam_passwd *sam_pass;
1782
1783         become_root(True);
1784         sam_pass = getsam21pwrid(user_rid);
1785         unbecome_root(True);
1786
1787         if (sam_pass == NULL)
1788         {
1789                 DEBUG(4,("User 0x%x not found\n", user_rid));
1790                 return False;
1791         }
1792
1793         DEBUG(3,("User:[%s]\n", sam_pass->nt_name));
1794
1795         make_sam_user_info10(id10, sam_pass->acct_ctrl); 
1796
1797         return True;
1798 }
1799
1800 /*************************************************************************
1801  get_user_info_21
1802  *************************************************************************/
1803 static BOOL get_user_info_21(SAM_USER_INFO_21 *id21, uint32 user_rid)
1804 {
1805         struct sam_passwd *sam_pass;
1806         LOGON_HRS hrs;
1807         int i;
1808
1809         become_root(True);
1810         sam_pass = getsam21pwrid(user_rid);
1811         unbecome_root(True);
1812
1813         if (sam_pass == NULL)
1814         {
1815                 DEBUG(4,("User 0x%x not found\n", user_rid));
1816                 return False;
1817         }
1818
1819         DEBUG(3,("User:[%s]\n", sam_pass->nt_name));
1820
1821         /* create a LOGON_HRS structure */
1822         hrs.len = sam_pass->hours_len;
1823         SMB_ASSERT_ARRAY(hrs.hours, hrs.len);
1824         for (i = 0; i < hrs.len; i++)
1825         {
1826                 hrs.hours[i] = sam_pass->hours[i];
1827         }
1828
1829         make_sam_user_info21(id21,
1830
1831                            &sam_pass->logon_time,
1832                            &sam_pass->logoff_time,
1833                            &sam_pass->kickoff_time,
1834                            &sam_pass->pass_last_set_time,
1835                            &sam_pass->pass_can_change_time,
1836                            &sam_pass->pass_must_change_time,
1837
1838                            sam_pass->nt_name, /* user_name */
1839                            sam_pass->full_name, /* full_name */
1840                            sam_pass->home_dir, /* home_dir */
1841                            sam_pass->dir_drive, /* dir_drive */
1842                            sam_pass->logon_script, /* logon_script */
1843                            sam_pass->profile_path, /* profile_path */
1844                            sam_pass->acct_desc, /* description */
1845                            sam_pass->workstations, /* workstations user can log in from */
1846                            sam_pass->unknown_str, /* don't know, yet */
1847                            sam_pass->munged_dial, /* dialin info.  contains dialin path and tel no */
1848
1849                            sam_pass->user_rid, /* RID user_id */
1850                            sam_pass->group_rid, /* RID group_id */
1851                            sam_pass->acct_ctrl,
1852
1853                            sam_pass->unknown_3, /* unknown_3 */
1854                            sam_pass->logon_divs, /* divisions per week */
1855                            &hrs, /* logon hours */
1856                            sam_pass->unknown_5,
1857                            sam_pass->unknown_6);
1858
1859         return True;
1860 }
1861
1862 /*******************************************************************
1863  samr_reply_query_userinfo
1864  ********************************************************************/
1865 static void samr_reply_query_userinfo(SAMR_Q_QUERY_USERINFO *q_u,
1866                                 prs_struct *rdata)
1867 {
1868         SAMR_R_QUERY_USERINFO r_u;
1869 #if 0
1870         SAM_USER_INFO_11 id11;
1871 #endif
1872         SAM_USER_INFO_10 id10;
1873         SAM_USER_INFO_21 id21;
1874         void *info = NULL;
1875
1876         uint32 status = 0x0;
1877         uint32 rid = 0x0;
1878
1879         DEBUG(5,("samr_reply_query_userinfo: %d\n", __LINE__));
1880
1881         /* search for the handle */
1882         if (status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->pol)) == -1))
1883         {
1884                 status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
1885         }
1886
1887         /* find the user's rid */
1888         if (status == 0x0 && (rid = get_lsa_policy_samr_rid(&(q_u->pol))) == 0xffffffff)
1889         {
1890                 status = 0xC0000000 | NT_STATUS_OBJECT_TYPE_MISMATCH;
1891         }
1892
1893         DEBUG(5,("samr_reply_query_userinfo: rid:0x%x\n", rid));
1894
1895         /* ok!  user info levels (there are lots: see MSDEV help), off we go... */
1896         if (status == 0x0)
1897         {
1898                 switch (q_u->switch_value)
1899                 {
1900                         case 0x10:
1901                         {
1902                                 info = (void*)&id10;
1903                                 status = get_user_info_10(&id10, rid) ? 0 : (0xC0000000 | NT_STATUS_NO_SUCH_USER);
1904                                 break;
1905                         }
1906 #if 0
1907 /* whoops - got this wrong.  i think.  or don't understand what's happening. */
1908                         case 0x11:
1909                         {
1910                                 NTTIME expire;
1911                                 info = (void*)&id11;
1912                                 
1913                                 expire.low  = 0xffffffff;
1914                                 expire.high = 0x7fffffff;
1915
1916                                 make_sam_user_info11(&id11, &expire, "BROOKFIELDS$", 0x03ef, 0x201, 0x0080);
1917
1918                                 break;
1919                         }
1920 #endif
1921                         case 21:
1922                         {
1923                                 info = (void*)&id21;
1924                                 status = get_user_info_21(&id21, rid) ? 0 : (0xC0000000 | NT_STATUS_NO_SUCH_USER);
1925                                 break;
1926                         }
1927
1928                         default:
1929                         {
1930                                 status = 0xC0000000 | NT_STATUS_INVALID_INFO_CLASS;
1931
1932                                 break;
1933                         }
1934                 }
1935         }
1936
1937         make_samr_r_query_userinfo(&r_u, q_u->switch_value, info, status);
1938
1939         /* store the response in the SMB stream */
1940         samr_io_r_query_userinfo("", &r_u, rdata, 0);
1941
1942         DEBUG(5,("samr_reply_query_userinfo: %d\n", __LINE__));
1943
1944 }
1945
1946 /*******************************************************************
1947  set_user_info_24
1948  ********************************************************************/
1949 static BOOL set_user_info_24(SAM_USER_INFO_24 *id24, uint32 rid)
1950 {
1951         struct sam_passwd *pwd = getsam21pwrid(rid);
1952         struct sam_passwd new_pwd;
1953         static uchar nt_hash[16];
1954         static uchar lm_hash[16];
1955         pstring new_pw;
1956
1957         if (pwd == NULL)
1958         {
1959                 return False;
1960         }
1961
1962         pwdb_init_sam(&new_pwd);
1963         copy_sam_passwd(&new_pwd, pwd);
1964
1965         if (!decode_pw_buffer(id24->pass, new_pw, sizeof(new_pw), True))
1966         {
1967                 return False;
1968         }
1969
1970 #ifdef DEBUG_PASSWORD
1971         DEBUG(0,("New Password: %s\n", new_pw));
1972 #endif
1973
1974         nt_lm_owf_gen(new_pw, nt_hash, lm_hash);
1975
1976         new_pwd.smb_passwd    = lm_hash;
1977         new_pwd.smb_nt_passwd = nt_hash;
1978
1979         return mod_sam21pwd_entry(&new_pwd, True);
1980 }
1981
1982 /*******************************************************************
1983  set_user_info_23
1984  ********************************************************************/
1985 static BOOL set_user_info_23(SAM_USER_INFO_23 *id23, uint32 rid)
1986 {
1987         struct sam_passwd *pwd = getsam21pwrid(rid);
1988         struct sam_passwd new_pwd;
1989         static uchar nt_hash[16];
1990         static uchar lm_hash[16];
1991         pstring new_pw;
1992
1993         if (pwd == NULL)
1994         {
1995                 return False;
1996         }
1997
1998         pwdb_init_sam(&new_pwd);
1999         copy_sam_passwd(&new_pwd, pwd);
2000         copy_id23_to_sam_passwd(&new_pwd, id23);
2001
2002         if (!decode_pw_buffer(id23->pass, new_pw, sizeof(new_pw), True))
2003         {
2004                 return False;
2005         }
2006
2007 #ifdef DEBUG_PASSWORD
2008         DEBUG(0,("New Password: %s\n", new_pw));
2009 #endif
2010
2011         nt_lm_owf_gen(new_pw, nt_hash, lm_hash);
2012
2013         new_pwd.smb_passwd    = lm_hash;
2014         new_pwd.smb_nt_passwd = nt_hash;
2015
2016         return mod_sam21pwd_entry(&new_pwd, True);
2017 }
2018
2019 /*******************************************************************
2020  api_samr_query_userinfo
2021  ********************************************************************/
2022 static void api_samr_query_userinfo( uint16 vuid, prs_struct *data, prs_struct *rdata)
2023 {
2024         SAMR_Q_QUERY_USERINFO q_u;
2025         samr_io_q_query_userinfo("", &q_u, data, 0);
2026         samr_reply_query_userinfo(&q_u, rdata);
2027 }
2028
2029
2030 /*******************************************************************
2031  samr_reply_set_userinfo
2032  ********************************************************************/
2033 static void samr_reply_set_userinfo(SAMR_Q_SET_USERINFO *q_u,
2034                                 prs_struct *rdata, uchar user_sess_key[16])
2035 {
2036         SAMR_R_SET_USERINFO r_u;
2037
2038         uint32 status = 0x0;
2039         uint32 rid = 0x0;
2040
2041         DEBUG(5,("samr_reply_set_userinfo: %d\n", __LINE__));
2042
2043         /* search for the handle */
2044         if (status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->pol)) == -1))
2045         {
2046                 status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
2047         }
2048
2049         /* find the user's rid */
2050         if (status == 0x0 && (rid = get_lsa_policy_samr_rid(&(q_u->pol))) == 0xffffffff)
2051         {
2052                 status = 0xC0000000 | NT_STATUS_OBJECT_TYPE_MISMATCH;
2053         }
2054
2055         DEBUG(5,("samr_reply_set_userinfo: rid:0x%x\n", rid));
2056
2057         /* ok!  user info levels (there are lots: see MSDEV help), off we go... */
2058         if (status == 0x0)
2059         {
2060                 switch (q_u->switch_value)
2061                 {
2062                         case 24:
2063                         {
2064                                 SAM_USER_INFO_24 *id24 = q_u->info.id24;
2065                                 SamOEMhash(id24->pass, user_sess_key, True);
2066                                 status = set_user_info_24(id24, rid) ? 0 : (0xC0000000 | NT_STATUS_ACCESS_DENIED);
2067                                 break;
2068                         }
2069
2070                         case 23:
2071                         {
2072                                 SAM_USER_INFO_23 *id23 = q_u->info.id23;
2073                                 SamOEMhash(id23->pass, user_sess_key, True);
2074                                 status = set_user_info_23(id23, rid) ? 0 : (0xC0000000 | NT_STATUS_ACCESS_DENIED);
2075                                 break;
2076                         }
2077
2078                         default:
2079                         {
2080                                 status = 0xC0000000 | NT_STATUS_INVALID_INFO_CLASS;
2081
2082                                 break;
2083                         }
2084                 }
2085         }
2086
2087         make_samr_r_set_userinfo(&r_u, status);
2088
2089         /* store the response in the SMB stream */
2090         samr_io_r_set_userinfo("", &r_u, rdata, 0);
2091
2092         DEBUG(5,("samr_reply_set_userinfo: %d\n", __LINE__));
2093
2094 }
2095
2096 /*******************************************************************
2097  api_samr_set_userinfo
2098  ********************************************************************/
2099 static void api_samr_set_userinfo( uint16 vuid, prs_struct *data, prs_struct *rdata)
2100 {
2101         user_struct *vuser = get_valid_user_struct(vuid);
2102         SAMR_Q_SET_USERINFO q_u;
2103         ZERO_STRUCT(q_u);
2104
2105 #ifdef DEBUG_PASSWORD
2106         DEBUG(100,("set user info: sess_key: "));
2107         dump_data(100, vuser->dc.user_sess_key, 16);
2108 #endif
2109         samr_io_q_set_userinfo("", &q_u, data, 0);
2110         samr_reply_set_userinfo(&q_u, rdata, vuser->dc.user_sess_key);
2111
2112         if (q_u.info.id != NULL)
2113         {
2114                 free(q_u.info.id);
2115         }
2116 }
2117
2118
2119 /*******************************************************************
2120  samr_reply_query_usergroups
2121  ********************************************************************/
2122 static void samr_reply_query_usergroups(SAMR_Q_QUERY_USERGROUPS *q_u,
2123                                 prs_struct *rdata)
2124 {
2125         SAMR_R_QUERY_USERGROUPS r_u;
2126         uint32 status = 0x0;
2127
2128         struct sam_passwd *sam_pass;
2129         DOM_GID *gids = NULL;
2130         int num_groups = 0;
2131         uint32 rid;
2132
2133         DEBUG(5,("samr_query_usergroups: %d\n", __LINE__));
2134
2135         /* find the policy handle.  open a policy on it. */
2136         if (status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->pol)) == -1))
2137         {
2138                 status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
2139         }
2140
2141         /* find the user's rid */
2142         if (status == 0x0 && (rid = get_lsa_policy_samr_rid(&(q_u->pol))) == 0xffffffff)
2143         {
2144                 status = 0xC0000000 | NT_STATUS_OBJECT_TYPE_MISMATCH;
2145         }
2146
2147         if (status == 0x0)
2148         {
2149                 become_root(True);
2150                 sam_pass = getsam21pwrid(rid);
2151                 unbecome_root(True);
2152
2153                 if (sam_pass == NULL)
2154                 {
2155                         status = 0xC0000000 | NT_STATUS_NO_SUCH_USER;
2156                 }
2157         }
2158
2159         if (status == 0x0)
2160         {
2161                 DOMAIN_GRP *mem_grp = NULL;
2162
2163                 become_root(True);
2164                 getusergroupsntnam(sam_pass->nt_name, &mem_grp, &num_groups);
2165                 unbecome_root(True);
2166
2167                 gids = NULL;
2168                 num_groups = make_dom_gids(mem_grp, num_groups, &gids);
2169
2170                 if (mem_grp != NULL)
2171                 {
2172                         free(mem_grp);
2173                 }
2174         }
2175
2176         /* construct the response.  lkclXXXX: gids are not copied! */
2177         make_samr_r_query_usergroups(&r_u, num_groups, gids, status);
2178
2179         /* store the response in the SMB stream */
2180         samr_io_r_query_usergroups("", &r_u, rdata, 0);
2181
2182         if (gids)
2183         {
2184                 free((char *)gids);
2185         }
2186
2187         DEBUG(5,("samr_query_usergroups: %d\n", __LINE__));
2188
2189 }
2190
2191 /*******************************************************************
2192  api_samr_query_usergroups
2193  ********************************************************************/
2194 static void api_samr_query_usergroups( uint16 vuid, prs_struct *data, prs_struct *rdata)
2195 {
2196         SAMR_Q_QUERY_USERGROUPS q_u;
2197         samr_io_q_query_usergroups("", &q_u, data, 0);
2198         samr_reply_query_usergroups(&q_u, rdata);
2199 }
2200
2201
2202 /*******************************************************************
2203  opens a samr alias by rid, returns a policy handle.
2204  ********************************************************************/
2205 static uint32 open_samr_alias(DOM_SID *sid, POLICY_HND *alias_pol,
2206                                 uint32 alias_rid)
2207 {
2208         BOOL pol_open = False;
2209         uint32 status = 0x0;
2210
2211         /* get a (unique) handle.  open a policy on it. */
2212         if (status == 0x0 && !(pol_open = open_lsa_policy_hnd(alias_pol)))
2213         {
2214                 status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
2215         }
2216
2217         DEBUG(0,("TODO: verify that the alias rid exists\n"));
2218
2219         /* associate a RID with the (unique) handle. */
2220         if (status == 0x0 && !set_lsa_policy_samr_rid(alias_pol, alias_rid))
2221         {
2222                 /* oh, whoops.  don't know what error message to return, here */
2223                 status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
2224         }
2225
2226         sid_append_rid(sid, alias_rid);
2227
2228         /* associate an alias SID with the (unique) handle. */
2229         if (status == 0x0 && !set_lsa_policy_samr_sid(alias_pol, sid))
2230         {
2231                 /* oh, whoops.  don't know what error message to return, here */
2232                 status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
2233         }
2234
2235         if (status != 0 && pol_open)
2236         {
2237                 close_lsa_policy_hnd(alias_pol);
2238         }
2239
2240         return status;
2241 }
2242
2243 /*******************************************************************
2244  samr_reply_create_dom_alias
2245  ********************************************************************/
2246 static void samr_reply_create_dom_alias(SAMR_Q_CREATE_DOM_ALIAS *q_u,
2247                                 prs_struct *rdata)
2248 {
2249         SAMR_R_CREATE_DOM_ALIAS r_u;
2250         DOM_SID dom_sid;
2251         LOCAL_GRP grp;
2252         POLICY_HND alias_pol;
2253         uint32 status = 0x0;
2254
2255         bzero(&alias_pol, sizeof(alias_pol));
2256
2257         DEBUG(5,("samr_create_dom_alias: %d\n", __LINE__));
2258
2259         /* find the policy handle.  open a policy on it. */
2260         if (status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->dom_pol)) == -1))
2261         {
2262                 status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
2263         }
2264
2265         /* find the domain sid */
2266         if (status == 0x0 && !get_lsa_policy_samr_sid(&q_u->dom_pol, &dom_sid))
2267         {
2268                 status = 0xC0000000 | NT_STATUS_OBJECT_TYPE_MISMATCH;
2269         }
2270
2271         if (!sid_equal(&dom_sid, &global_sam_sid))
2272         {
2273                 status = 0xC0000000 | NT_STATUS_ACCESS_DENIED;
2274         }
2275
2276         if (status == 0x0)
2277         {
2278                 unistr2_to_ascii(grp.name, &q_u->uni_acct_desc, sizeof(grp.name)-1);
2279                 fstrcpy(grp.comment, "");
2280                 grp.rid = 0xffffffff;
2281
2282                 become_root(True);
2283                 status = add_alias_entry(&grp) ? 0 : (0xC0000000 | NT_STATUS_ACCESS_DENIED);
2284                 unbecome_root(True);
2285         }
2286
2287         if (status == 0x0)
2288         {
2289                 status = open_samr_alias(&dom_sid, &alias_pol, grp.rid);
2290         }
2291
2292         /* construct the response. */
2293         make_samr_r_create_dom_alias(&r_u, &alias_pol, grp.rid, status);
2294
2295         /* store the response in the SMB stream */
2296         samr_io_r_create_dom_alias("", &r_u, rdata, 0);
2297
2298         DEBUG(5,("samr_create_dom_alias: %d\n", __LINE__));
2299
2300 }
2301
2302 /*******************************************************************
2303  api_samr_create_dom_alias
2304  ********************************************************************/
2305 static void api_samr_create_dom_alias( uint16 vuid, prs_struct *data, prs_struct *rdata)
2306 {
2307         SAMR_Q_CREATE_DOM_ALIAS q_u;
2308         samr_io_q_create_dom_alias("", &q_u, data, 0);
2309         samr_reply_create_dom_alias(&q_u, rdata);
2310 }
2311
2312
2313 /*******************************************************************
2314  opens a samr group by rid, returns a policy handle.
2315  ********************************************************************/
2316 static uint32 open_samr_group(DOM_SID *sid, POLICY_HND *group_pol,
2317                                 uint32 group_rid)
2318 {
2319         BOOL pol_open = False;
2320         uint32 status = 0x0;
2321
2322         /* get a (unique) handle.  open a policy on it. */
2323         if (status == 0x0 && !(pol_open = open_lsa_policy_hnd(group_pol)))
2324         {
2325                 status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
2326         }
2327
2328         DEBUG(0,("TODO: verify that the group rid exists\n"));
2329
2330         /* associate a RID with the (unique) handle. */
2331         if (status == 0x0 && !set_lsa_policy_samr_rid(group_pol, group_rid))
2332         {
2333                 /* oh, whoops.  don't know what error message to return, here */
2334                 status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
2335         }
2336
2337         sid_append_rid(sid, group_rid);
2338
2339         /* associate an group SID with the (unique) handle. */
2340         if (status == 0x0 && !set_lsa_policy_samr_sid(group_pol, sid))
2341         {
2342                 /* oh, whoops.  don't know what error message to return, here */
2343                 status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
2344         }
2345
2346         if (status != 0 && pol_open)
2347         {
2348                 close_lsa_policy_hnd(group_pol);
2349         }
2350
2351         return status;
2352 }
2353
2354 /*******************************************************************
2355  samr_reply_create_dom_group
2356  ********************************************************************/
2357 static void samr_reply_create_dom_group(SAMR_Q_CREATE_DOM_GROUP *q_u,
2358                                 prs_struct *rdata)
2359 {
2360         SAMR_R_CREATE_DOM_GROUP r_u;
2361         DOM_SID dom_sid;
2362         DOMAIN_GRP grp;
2363         POLICY_HND group_pol;
2364         uint32 status = 0x0;
2365
2366         bzero(&group_pol, sizeof(group_pol));
2367
2368         DEBUG(5,("samr_create_dom_group: %d\n", __LINE__));
2369
2370         /* find the policy handle.  open a policy on it. */
2371         if (status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->pol)) == -1))
2372         {
2373                 status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
2374         }
2375
2376         /* find the domain sid */
2377         if (status == 0x0 && !get_lsa_policy_samr_sid(&q_u->pol, &dom_sid))
2378         {
2379                 status = 0xC0000000 | NT_STATUS_OBJECT_TYPE_MISMATCH;
2380         }
2381
2382         if (!sid_equal(&dom_sid, &global_sam_sid))
2383         {
2384                 status = 0xC0000000 | NT_STATUS_ACCESS_DENIED;
2385         }
2386
2387         if (status == 0x0)
2388         {
2389                 unistr2_to_ascii(grp.name, &q_u->uni_acct_desc, sizeof(grp.name)-1);
2390                 fstrcpy(grp.comment, "");
2391                 grp.rid = 0xffffffff;
2392                 grp.attr = 0x07;
2393
2394                 become_root(True);
2395                 status = add_group_entry(&grp) ? 0x0 : (0xC0000000 | NT_STATUS_ACCESS_DENIED);
2396                 unbecome_root(True);
2397         }
2398
2399         if (status == 0x0)
2400         {
2401                 status = open_samr_group(&dom_sid, &group_pol, grp.rid);
2402         }
2403
2404         /* construct the response. */
2405         make_samr_r_create_dom_group(&r_u, &group_pol, grp.rid, status);
2406
2407         /* store the response in the SMB stream */
2408         samr_io_r_create_dom_group("", &r_u, rdata, 0);
2409
2410         DEBUG(5,("samr_create_dom_group: %d\n", __LINE__));
2411
2412 }
2413
2414 /*******************************************************************
2415  api_samr_create_dom_group
2416  ********************************************************************/
2417 static void api_samr_create_dom_group( uint16 vuid, prs_struct *data, prs_struct *rdata)
2418 {
2419         SAMR_Q_CREATE_DOM_GROUP q_u;
2420         samr_io_q_create_dom_group("", &q_u, data, 0);
2421         samr_reply_create_dom_group(&q_u, rdata);
2422 }
2423
2424
2425 /*******************************************************************
2426  samr_reply_query_dom_info
2427  ********************************************************************/
2428 static void samr_reply_query_dom_info(SAMR_Q_QUERY_DOMAIN_INFO *q_u,
2429                                 prs_struct *rdata)
2430 {
2431         SAMR_R_QUERY_DOMAIN_INFO r_u;
2432         SAM_UNK_CTR ctr;
2433         uint16 switch_value = 0x0;
2434         uint32 status = 0x0;
2435
2436         ZERO_STRUCT(r_u);
2437         ZERO_STRUCT(ctr);
2438
2439         r_u.ctr = &ctr;
2440
2441         DEBUG(5,("samr_reply_query_dom_info: %d\n", __LINE__));
2442
2443         /* find the policy handle.  open a policy on it. */
2444         if (r_u.status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->domain_pol)) == -1))
2445         {
2446                 r_u.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
2447                 DEBUG(5,("samr_reply_query_dom_info: invalid handle\n"));
2448         }
2449
2450         if (status == 0x0)
2451         {
2452                 switch (q_u->switch_value)
2453                 {
2454                         case 0x07:
2455                         {
2456                                 switch_value = 0x7;
2457                                 make_unk_info7(&ctr.info.inf7);
2458
2459                                 break;
2460                         }
2461                         case 0x06:
2462                         {
2463                                 switch_value = 0x6;
2464                                 make_unk_info6(&ctr.info.inf6);
2465
2466                                 break;
2467                         }
2468                         case 0x03:
2469                         {
2470                                 switch_value = 0x3;
2471                                 make_unk_info3(&ctr.info.inf3);
2472
2473                                 break;
2474                         }
2475                         case 0x02:
2476                         {
2477                                 switch_value = 0x2;
2478                                 make_unk_info2(&ctr.info.inf2, global_sam_name, global_myname);
2479
2480                                 break;
2481                         }
2482                         case 0x01:
2483                         {
2484                                 switch_value = 0x1;
2485                                 make_unk_info1(&ctr.info.inf1);
2486
2487                                 break;
2488                         }
2489                         default:
2490                         {
2491                                 status = 0xC0000000 | NT_STATUS_INVALID_INFO_CLASS;
2492                                 break;
2493                         }
2494                 }
2495         }
2496
2497         make_samr_r_query_dom_info(&r_u, switch_value, &ctr, status);
2498
2499         /* store the response in the SMB stream */
2500         samr_io_r_query_dom_info("", &r_u, rdata, 0);
2501
2502         DEBUG(5,("samr_query_dom_info: %d\n", __LINE__));
2503
2504 }
2505
2506 /*******************************************************************
2507  api_samr_query_dom_info
2508  ********************************************************************/
2509 static void api_samr_query_dom_info( uint16 vuid, prs_struct *data, prs_struct *rdata)
2510 {
2511         SAMR_Q_QUERY_DOMAIN_INFO q_e;
2512         samr_io_q_query_dom_info("", &q_e, data, 0);
2513         samr_reply_query_dom_info(&q_e, rdata);
2514 }
2515
2516
2517
2518 /*******************************************************************
2519  samr_reply_create_user
2520  ********************************************************************/
2521 static void samr_reply_create_user(SAMR_Q_CREATE_USER *q_u,
2522                                 prs_struct *rdata)
2523 {
2524         struct sam_passwd *sam_pass;
2525         fstring user_name;
2526
2527         SAMR_R_CREATE_USER r_u;
2528         POLICY_HND pol;
2529         uint32 status = 0x0;
2530         uint32 user_rid = 0xffffffff;
2531         BOOL pol_open = False;
2532
2533         /* find the machine account: tell the caller if it exists.
2534            lkclXXXX i have *no* idea if this is a problem or not
2535            or even if you are supposed to construct a different
2536            reply if the account already exists...
2537          */
2538
2539         /* find the policy handle.  open a policy on it. */
2540         if (status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->domain_pol)) == -1))
2541         {
2542                 status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
2543         }
2544
2545         /* get a (unique) handle.  open a policy on it. */
2546         if (status == 0x0 && !(pol_open = open_lsa_policy_hnd(&pol)))
2547         {
2548                 status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
2549         }
2550
2551         unistr2_to_ascii(user_name, &q_u->uni_name, sizeof(user_name)-1);
2552
2553         sam_pass = getsam21pwntnam(user_name);
2554
2555         if (sam_pass != NULL)
2556         {
2557                 /* account exists: say so */
2558                 status = 0xC0000000 | NT_STATUS_USER_EXISTS;
2559         }
2560         else
2561         {
2562                 pstring err_str;
2563                 pstring msg_str;
2564
2565                 if (!local_password_change(user_name, True,
2566                           q_u->acb_info, 0xffff,
2567                           NULL,
2568                           err_str, sizeof(err_str),
2569                           msg_str, sizeof(msg_str)))
2570                 {
2571                         DEBUG(0,("%s\n", err_str));
2572                         status = 0xC0000000 | NT_STATUS_ACCESS_DENIED;
2573                 }
2574                 else
2575                 {
2576                         sam_pass = getsam21pwntnam(user_name);
2577                         if (sam_pass == NULL)
2578                         {
2579                                 /* account doesn't exist: say so */
2580                                 status = 0xC0000000 | NT_STATUS_ACCESS_DENIED;
2581                         }
2582                         else
2583                         {
2584                                 user_rid = sam_pass->user_rid;
2585                         }
2586                 }
2587         }
2588
2589         /* associate the RID with the (unique) handle. */
2590         if (status == 0x0 && !set_lsa_policy_samr_rid(&pol, user_rid))
2591         {
2592                 /* oh, whoops.  don't know what error message to return, here */
2593                 status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
2594         }
2595
2596         if (status != 0 && pol_open)
2597         {
2598                 close_lsa_policy_hnd(&pol);
2599         }
2600
2601         DEBUG(5,("samr_create_user: %d\n", __LINE__));
2602
2603         make_samr_r_create_user(&r_u, &pol, 0x000703ff, user_rid, status);
2604
2605         /* store the response in the SMB stream */
2606         samr_io_r_create_user("", &r_u, rdata, 0);
2607
2608         DEBUG(5,("samr_create_user: %d\n", __LINE__));
2609
2610 }
2611
2612 /*******************************************************************
2613  api_samr_create_user
2614  ********************************************************************/
2615 static void api_samr_create_user( uint16 vuid, prs_struct *data, prs_struct *rdata)
2616 {
2617         SAMR_Q_CREATE_USER q_u;
2618
2619         /* grab the samr unknown 32 */
2620         samr_io_q_create_user("", &q_u, data, 0);
2621
2622         /* construct reply. */
2623         samr_reply_create_user(&q_u, rdata);
2624 }
2625
2626
2627 /*******************************************************************
2628  samr_reply_connect_anon
2629  ********************************************************************/
2630 static void samr_reply_connect_anon(SAMR_Q_CONNECT_ANON *q_u,
2631                                 prs_struct *rdata)
2632 {
2633         SAMR_R_CONNECT_ANON r_u;
2634         BOOL pol_open = False;
2635
2636         /* set up the SAMR connect_anon response */
2637
2638         r_u.status = 0x0;
2639         /* get a (unique) handle.  open a policy on it. */
2640         if (r_u.status == 0x0 && !(pol_open = open_lsa_policy_hnd(&(r_u.connect_pol))))
2641         {
2642                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
2643         }
2644
2645         /* associate the domain SID with the (unique) handle. */
2646         if (r_u.status == 0x0 && !set_lsa_policy_samr_pol_status(&(r_u.connect_pol), q_u->unknown_0))
2647         {
2648                 /* oh, whoops.  don't know what error message to return, here */
2649                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
2650         }
2651
2652         if (r_u.status != 0 && pol_open)
2653         {
2654                 close_lsa_policy_hnd(&(r_u.connect_pol));
2655         }
2656
2657         DEBUG(5,("samr_connect_anon: %d\n", __LINE__));
2658
2659         /* store the response in the SMB stream */
2660         samr_io_r_connect_anon("", &r_u, rdata, 0);
2661
2662         DEBUG(5,("samr_connect_anon: %d\n", __LINE__));
2663
2664 }
2665
2666 /*******************************************************************
2667  api_samr_connect_anon
2668  ********************************************************************/
2669 static void api_samr_connect_anon( uint16 vuid, prs_struct *data, prs_struct *rdata)
2670 {
2671         SAMR_Q_CONNECT_ANON q_u;
2672         samr_io_q_connect_anon("", &q_u, data, 0);
2673         samr_reply_connect_anon(&q_u, rdata);
2674 }
2675
2676 /*******************************************************************
2677  samr_reply_connect
2678  ********************************************************************/
2679 static void samr_reply_connect(SAMR_Q_CONNECT *q_u,
2680                                 prs_struct *rdata)
2681 {
2682         SAMR_R_CONNECT r_u;
2683         BOOL pol_open = False;
2684
2685         /* set up the SAMR connect response */
2686
2687         r_u.status = 0x0;
2688         /* get a (unique) handle.  open a policy on it. */
2689         if (r_u.status == 0x0 && !(pol_open = open_lsa_policy_hnd(&(r_u.connect_pol))))
2690         {
2691                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
2692         }
2693
2694         /* associate the domain SID with the (unique) handle. */
2695         if (r_u.status == 0x0 && !set_lsa_policy_samr_pol_status(&(r_u.connect_pol), q_u->unknown_0))
2696         {
2697                 /* oh, whoops.  don't know what error message to return, here */
2698                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
2699         }
2700
2701         if (r_u.status != 0 && pol_open)
2702         {
2703                 close_lsa_policy_hnd(&(r_u.connect_pol));
2704         }
2705
2706         DEBUG(5,("samr_connect: %d\n", __LINE__));
2707
2708         /* store the response in the SMB stream */
2709         samr_io_r_connect("", &r_u, rdata, 0);
2710
2711         DEBUG(5,("samr_connect: %d\n", __LINE__));
2712
2713 }
2714
2715 /*******************************************************************
2716  api_samr_connect
2717  ********************************************************************/
2718 static void api_samr_connect( uint16 vuid, prs_struct *data, prs_struct *rdata)
2719 {
2720         SAMR_Q_CONNECT q_u;
2721         samr_io_q_connect("", &q_u, data, 0);
2722         samr_reply_connect(&q_u, rdata);
2723 }
2724
2725 /*******************************************************************
2726  samr_reply_open_alias
2727  ********************************************************************/
2728 static void samr_reply_open_alias(SAMR_Q_OPEN_ALIAS *q_u,
2729                                 prs_struct *rdata)
2730 {
2731         SAMR_R_OPEN_ALIAS r_u;
2732         DOM_SID sid;
2733         BOOL pol_open = False;
2734
2735         /* set up the SAMR open_alias response */
2736
2737         r_u.status = 0x0;
2738         if (r_u.status == 0x0 && !get_lsa_policy_samr_sid(&q_u->dom_pol, &sid))
2739         {
2740                 r_u.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
2741         }
2742
2743         /* get a (unique) handle.  open a policy on it. */
2744         if (r_u.status == 0x0 && !(pol_open = open_lsa_policy_hnd(&(r_u.pol))))
2745         {
2746                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
2747         }
2748
2749         DEBUG(0,("TODO: verify that the alias rid exists\n"));
2750
2751         /* associate a RID with the (unique) handle. */
2752         if (r_u.status == 0x0 && !set_lsa_policy_samr_rid(&(r_u.pol), q_u->rid_alias))
2753         {
2754                 /* oh, whoops.  don't know what error message to return, here */
2755                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
2756         }
2757
2758         sid_append_rid(&sid, q_u->rid_alias);
2759
2760         /* associate an alias SID with the (unique) handle. */
2761         if (r_u.status == 0x0 && !set_lsa_policy_samr_sid(&(r_u.pol), &sid))
2762         {
2763                 /* oh, whoops.  don't know what error message to return, here */
2764                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
2765         }
2766
2767         if (r_u.status != 0 && pol_open)
2768         {
2769                 close_lsa_policy_hnd(&(r_u.pol));
2770         }
2771
2772         DEBUG(5,("samr_open_alias: %d\n", __LINE__));
2773
2774         /* store the response in the SMB stream */
2775         samr_io_r_open_alias("", &r_u, rdata, 0);
2776
2777         DEBUG(5,("samr_open_alias: %d\n", __LINE__));
2778
2779 }
2780
2781 /*******************************************************************
2782  api_samr_open_alias
2783  ********************************************************************/
2784 static void api_samr_open_alias( uint16 vuid, prs_struct *data, prs_struct *rdata)
2785                                 
2786 {
2787         SAMR_Q_OPEN_ALIAS q_u;
2788         samr_io_q_open_alias("", &q_u, data, 0);
2789         samr_reply_open_alias(&q_u, rdata);
2790 }
2791
2792 /*******************************************************************
2793  samr_reply_open_group
2794  ********************************************************************/
2795 static void samr_reply_open_group(SAMR_Q_OPEN_GROUP *q_u,
2796                                 prs_struct *rdata)
2797 {
2798         SAMR_R_OPEN_GROUP r_u;
2799         DOM_SID sid;
2800
2801         DEBUG(5,("samr_open_group: %d\n", __LINE__));
2802
2803         r_u.status = 0x0;
2804
2805         /* find the domain sid associated with the policy handle */
2806         if (r_u.status == 0x0 && !get_lsa_policy_samr_sid(&q_u->domain_pol, &sid))
2807         {
2808                 r_u.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
2809         }
2810
2811         if (r_u.status == 0x0 && !sid_equal(&sid, &global_sam_sid))
2812         {
2813                 r_u.status = 0xC0000000 | NT_STATUS_ACCESS_DENIED;
2814         }
2815
2816         if (r_u.status == 0x0)
2817         {
2818                 r_u.status = open_samr_group(&sid, &r_u.pol, q_u->rid_group);
2819         }
2820
2821         /* store the response in the SMB stream */
2822         samr_io_r_open_group("", &r_u, rdata, 0);
2823
2824         DEBUG(5,("samr_open_group: %d\n", __LINE__));
2825
2826 }
2827
2828 /*******************************************************************
2829  api_samr_open_group
2830  ********************************************************************/
2831 static void api_samr_open_group( uint16 vuid, prs_struct *data, prs_struct *rdata)
2832                                 
2833 {
2834         SAMR_Q_OPEN_GROUP q_u;
2835         samr_io_q_open_group("", &q_u, data, 0);
2836         samr_reply_open_group(&q_u, rdata);
2837 }
2838
2839 /*******************************************************************
2840  samr_reply_lookup_domain
2841  ********************************************************************/
2842 static void samr_reply_lookup_domain(SAMR_Q_LOOKUP_DOMAIN *q_u,
2843                                 prs_struct *rdata)
2844 {
2845         SAMR_R_LOOKUP_DOMAIN r_u;
2846         fstring domain;
2847
2848         DEBUG(5,("samr_lookup_domain: %d\n", __LINE__));
2849
2850         r_u.ptr_sid = 0;
2851         r_u.status = 0x0;
2852
2853         /* find the connection policy handle */
2854         if (find_lsa_policy_by_hnd(&(q_u->connect_pol)) == -1)
2855         {
2856                 r_u.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
2857         }
2858
2859         if (r_u.status == 0x0)
2860         {
2861                 unistr2_to_ascii(domain, &(q_u->uni_domain), sizeof(domain));
2862                 DEBUG(5, ("Lookup Domain: %s\n", domain));
2863
2864                 /* check it's one of ours */
2865                 if (strequal(domain, global_sam_name))
2866                 {
2867                         make_dom_sid2(&(r_u.dom_sid), &global_sam_sid);
2868                         r_u.ptr_sid = 1;
2869                 }
2870                 else if (strequal(domain, "BUILTIN"))
2871                 {
2872                         make_dom_sid2(&(r_u.dom_sid), &global_sid_S_1_5_20);
2873                         r_u.ptr_sid = 1;
2874                 }
2875                 else
2876                 {
2877                         r_u.status = 0xC0000000 | NT_STATUS_NO_SUCH_DOMAIN;
2878                 }
2879         }
2880
2881         /* store the response in the SMB stream */
2882         samr_io_r_lookup_domain("", &r_u, rdata, 0);
2883
2884         DEBUG(5,("samr_lookup_domain: %d\n", __LINE__));
2885 }
2886
2887 /*******************************************************************
2888  api_samr_lookup_domain
2889  ********************************************************************/
2890 static void api_samr_lookup_domain( uint16 vuid, prs_struct *data, prs_struct *rdata)
2891 {
2892         SAMR_Q_LOOKUP_DOMAIN q_u;
2893         samr_io_q_lookup_domain("", &q_u, data, 0);
2894         samr_reply_lookup_domain(&q_u, rdata);
2895 }
2896
2897 /*******************************************************************
2898  array of \PIPE\samr operations
2899  ********************************************************************/
2900 static struct api_struct api_samr_cmds [] =
2901 {
2902         { "SAMR_CLOSE_HND"        , SAMR_CLOSE_HND        , api_samr_close_hnd        },
2903         { "SAMR_CONNECT"          , SAMR_CONNECT          , api_samr_connect          },
2904         { "SAMR_CONNECT_ANON"     , SAMR_CONNECT_ANON     , api_samr_connect_anon     },
2905         { "SAMR_ENUM_DOM_USERS"   , SAMR_ENUM_DOM_USERS   , api_samr_enum_dom_users   },
2906         { "SAMR_ENUM_DOM_GROUPS"  , SAMR_ENUM_DOM_GROUPS  , api_samr_enum_dom_groups  },
2907         { "SAMR_ENUM_DOM_ALIASES" , SAMR_ENUM_DOM_ALIASES , api_samr_enum_dom_aliases },
2908         { "SAMR_QUERY_USERALIASES", SAMR_QUERY_USERALIASES, api_samr_query_useraliases},
2909         { "SAMR_QUERY_ALIASMEM"   , SAMR_QUERY_ALIASMEM   , api_samr_query_aliasmem   },
2910         { "SAMR_QUERY_GROUPMEM"   , SAMR_QUERY_GROUPMEM   , api_samr_query_groupmem   },
2911         { "SAMR_ADD_ALIASMEM"     , SAMR_ADD_ALIASMEM     , api_samr_add_aliasmem     },
2912         { "SAMR_DEL_ALIASMEM"     , SAMR_DEL_ALIASMEM     , api_samr_del_aliasmem     },
2913         { "SAMR_ADD_GROUPMEM"     , SAMR_ADD_GROUPMEM     , api_samr_add_groupmem     },
2914         { "SAMR_DEL_GROUPMEM"     , SAMR_DEL_GROUPMEM     , api_samr_del_groupmem     },
2915         { "SAMR_DELETE_DOM_GROUP" , SAMR_DELETE_DOM_GROUP , api_samr_delete_dom_group },
2916         { "SAMR_DELETE_DOM_ALIAS" , SAMR_DELETE_DOM_ALIAS , api_samr_delete_dom_alias },
2917         { "SAMR_CREATE_DOM_GROUP" , SAMR_CREATE_DOM_GROUP , api_samr_create_dom_group },
2918         { "SAMR_CREATE_DOM_ALIAS" , SAMR_CREATE_DOM_ALIAS , api_samr_create_dom_alias },
2919         { "SAMR_LOOKUP_NAMES"     , SAMR_LOOKUP_NAMES     , api_samr_lookup_names     },
2920         { "SAMR_OPEN_USER"        , SAMR_OPEN_USER        , api_samr_open_user        },
2921         { "SAMR_QUERY_USERINFO"   , SAMR_QUERY_USERINFO   , api_samr_query_userinfo   },
2922         { "SAMR_SET_USERINFO"     , SAMR_SET_USERINFO     , api_samr_set_userinfo     },
2923         { "SAMR_QUERY_DOMAIN_INFO", SAMR_QUERY_DOMAIN_INFO, api_samr_query_dom_info   },
2924         { "SAMR_QUERY_USERGROUPS" , SAMR_QUERY_USERGROUPS , api_samr_query_usergroups },
2925         { "SAMR_QUERY_DISPINFO"   , SAMR_QUERY_DISPINFO   , api_samr_query_dispinfo   },
2926         { "SAMR_QUERY_DISPINFO3"  , SAMR_QUERY_DISPINFO3  , api_samr_query_dispinfo   },
2927         { "SAMR_QUERY_DISPINFO4"  , SAMR_QUERY_DISPINFO4  , api_samr_query_dispinfo   },
2928         { "SAMR_QUERY_ALIASINFO"  , SAMR_QUERY_ALIASINFO  , api_samr_query_aliasinfo  },
2929         { "SAMR_QUERY_GROUPINFO"  , SAMR_QUERY_GROUPINFO  , api_samr_query_groupinfo  },
2930         { "SAMR_CREATE_USER"      , SAMR_CREATE_USER      , api_samr_create_user      },
2931         { "SAMR_LOOKUP_RIDS"      , SAMR_LOOKUP_RIDS      , api_samr_lookup_rids      },
2932         { "SAMR_UNKNOWN_38"       , SAMR_UNKNOWN_38       , api_samr_unknown_38       },
2933         { "SAMR_CHGPASSWD_USER"   , SAMR_CHGPASSWD_USER   , api_samr_chgpasswd_user   },
2934         { "SAMR_OPEN_ALIAS"       , SAMR_OPEN_ALIAS       , api_samr_open_alias       },
2935         { "SAMR_OPEN_GROUP"       , SAMR_OPEN_GROUP       , api_samr_open_group       },
2936         { "SAMR_OPEN_DOMAIN"      , SAMR_OPEN_DOMAIN      , api_samr_open_domain      },
2937         { "SAMR_LOOKUP_DOMAIN"    , SAMR_LOOKUP_DOMAIN    , api_samr_lookup_domain    },
2938         { "SAMR_UNKNOWN_3"        , SAMR_UNKNOWN_3        , api_samr_unknown_3        },
2939         { "SAMR_UNKNOWN_2C"       , SAMR_UNKNOWN_2C       , api_samr_unknown_2c       },
2940         { NULL                    , 0                     , NULL                      }
2941 };
2942
2943 /*******************************************************************
2944  receives a samr pipe and responds.
2945  ********************************************************************/
2946 BOOL api_samr_rpc(pipes_struct *p, prs_struct *data)
2947 {
2948     return api_rpcTNP(p, "api_samr_rpc", api_samr_cmds, data);
2949 }
2950