SAM database "set user info".
[samba.git] / source3 / rpc_server / srv_samr.c
1
2 /* 
3  *  Unix SMB/Netbios implementation.
4  *  Version 1.9.
5  *  RPC Pipe client / server routines
6  *  Copyright (C) Andrew Tridgell              1992-1997,
7  *  Copyright (C) Luke Kenneth Casson Leighton 1996-1997,
8  *  Copyright (C) Paul Ashton                       1997.
9  *  
10  *  This program is free software; you can redistribute it and/or modify
11  *  it under the terms of the GNU General Public License as published by
12  *  the Free Software Foundation; either version 2 of the License, or
13  *  (at your option) any later version.
14  *  
15  *  This program is distributed in the hope that it will be useful,
16  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *  GNU General Public License for more details.
19  *  
20  *  You should have received a copy of the GNU General Public License
21  *  along with this program; if not, write to the Free Software
22  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23  */
24
25
26 #include "includes.h"
27 #include "nterr.h"
28
29 extern int DEBUGLEVEL;
30
31 extern fstring global_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 = 0x105; /* 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_23
1948  ********************************************************************/
1949 static BOOL set_user_info_23(SAM_USER_INFO_23 *id23, uint32 rid)
1950 {
1951         static struct sam_passwd *pwd;
1952         fstring new_pw;
1953         if (!decode_pw_buffer(id23->pass, new_pw, sizeof(new_pw), True))
1954         {
1955                 return False;
1956         }
1957 #ifdef DEBUG_PASSWORD
1958         DEBUG(0,("New Password: %s\n", new_pw));
1959 #endif
1960 #if 0
1961         return mod_sam21pwd_entry(&pwd, True);
1962 #else
1963         return True;
1964 #endif
1965 }
1966
1967 /*******************************************************************
1968  api_samr_query_userinfo
1969  ********************************************************************/
1970 static void api_samr_query_userinfo( uint16 vuid, prs_struct *data, prs_struct *rdata)
1971 {
1972         SAMR_Q_QUERY_USERINFO q_u;
1973         samr_io_q_query_userinfo("", &q_u, data, 0);
1974         samr_reply_query_userinfo(&q_u, rdata);
1975 }
1976
1977
1978 /*******************************************************************
1979  samr_reply_set_userinfo
1980  ********************************************************************/
1981 static void samr_reply_set_userinfo(SAMR_Q_SET_USERINFO *q_u,
1982                                 prs_struct *rdata, uchar user_sess_key[16])
1983 {
1984         SAMR_R_SET_USERINFO r_u;
1985
1986         uint32 status = 0x0;
1987         uint32 rid = 0x0;
1988
1989         DEBUG(5,("samr_reply_set_userinfo: %d\n", __LINE__));
1990
1991         /* search for the handle */
1992         if (status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->pol)) == -1))
1993         {
1994                 status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
1995         }
1996
1997         /* find the user's rid */
1998         if (status == 0x0 && (rid = get_lsa_policy_samr_rid(&(q_u->pol))) == 0xffffffff)
1999         {
2000                 status = 0xC0000000 | NT_STATUS_OBJECT_TYPE_MISMATCH;
2001         }
2002
2003         DEBUG(5,("samr_reply_set_userinfo: rid:0x%x\n", rid));
2004
2005         /* ok!  user info levels (there are lots: see MSDEV help), off we go... */
2006         if (status == 0x0)
2007         {
2008                 switch (q_u->switch_value)
2009                 {
2010                         case 23:
2011                         {
2012                                 SAM_USER_INFO_23 *id23 = q_u->info.id23;
2013                                 SamOEMhash(id23->pass, user_sess_key, True);
2014                                 status = set_user_info_23(id23, rid) ? 0 : (0xC0000000 | NT_STATUS_ACCESS_DENIED);
2015                                 break;
2016                         }
2017
2018                         default:
2019                         {
2020                                 status = 0xC0000000 | NT_STATUS_INVALID_INFO_CLASS;
2021
2022                                 break;
2023                         }
2024                 }
2025         }
2026
2027         make_samr_r_set_userinfo(&r_u, status);
2028
2029         /* store the response in the SMB stream */
2030         samr_io_r_set_userinfo("", &r_u, rdata, 0);
2031
2032         DEBUG(5,("samr_reply_set_userinfo: %d\n", __LINE__));
2033
2034 }
2035
2036 /*******************************************************************
2037  api_samr_set_userinfo
2038  ********************************************************************/
2039 static void api_samr_set_userinfo( uint16 vuid, prs_struct *data, prs_struct *rdata)
2040 {
2041         user_struct *vuser = get_valid_user_struct(vuid);
2042         SAMR_Q_SET_USERINFO q_u;
2043         ZERO_STRUCT(q_u);
2044
2045 #ifdef DEBUG_PASSWORD
2046         DEBUG(100,("set user info: sess_key: "));
2047         dump_data(100, vuser->dc.user_sess_key, 16);
2048 #endif
2049         samr_io_q_set_userinfo("", &q_u, data, 0);
2050         samr_reply_set_userinfo(&q_u, rdata, vuser->dc.user_sess_key);
2051
2052         if (q_u.info.id != NULL)
2053         {
2054                 free(q_u.info.id);
2055         }
2056 }
2057
2058
2059 /*******************************************************************
2060  samr_reply_query_usergroups
2061  ********************************************************************/
2062 static void samr_reply_query_usergroups(SAMR_Q_QUERY_USERGROUPS *q_u,
2063                                 prs_struct *rdata)
2064 {
2065         SAMR_R_QUERY_USERGROUPS r_u;
2066         uint32 status = 0x0;
2067
2068         struct sam_passwd *sam_pass;
2069         DOM_GID *gids = NULL;
2070         int num_groups = 0;
2071         uint32 rid;
2072
2073         DEBUG(5,("samr_query_usergroups: %d\n", __LINE__));
2074
2075         /* find the policy handle.  open a policy on it. */
2076         if (status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->pol)) == -1))
2077         {
2078                 status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
2079         }
2080
2081         /* find the user's rid */
2082         if (status == 0x0 && (rid = get_lsa_policy_samr_rid(&(q_u->pol))) == 0xffffffff)
2083         {
2084                 status = 0xC0000000 | NT_STATUS_OBJECT_TYPE_MISMATCH;
2085         }
2086
2087         if (status == 0x0)
2088         {
2089                 become_root(True);
2090                 sam_pass = getsam21pwrid(rid);
2091                 unbecome_root(True);
2092
2093                 if (sam_pass == NULL)
2094                 {
2095                         status = 0xC0000000 | NT_STATUS_NO_SUCH_USER;
2096                 }
2097         }
2098
2099         if (status == 0x0)
2100         {
2101                 DOMAIN_GRP *mem_grp = NULL;
2102
2103                 become_root(True);
2104                 getusergroupsntnam(sam_pass->nt_name, &mem_grp, &num_groups);
2105                 unbecome_root(True);
2106
2107                 gids = NULL;
2108                 num_groups = make_dom_gids(mem_grp, num_groups, &gids);
2109
2110                 if (mem_grp != NULL)
2111                 {
2112                         free(mem_grp);
2113                 }
2114         }
2115
2116         /* construct the response.  lkclXXXX: gids are not copied! */
2117         make_samr_r_query_usergroups(&r_u, num_groups, gids, status);
2118
2119         /* store the response in the SMB stream */
2120         samr_io_r_query_usergroups("", &r_u, rdata, 0);
2121
2122         if (gids)
2123         {
2124                 free((char *)gids);
2125         }
2126
2127         DEBUG(5,("samr_query_usergroups: %d\n", __LINE__));
2128
2129 }
2130
2131 /*******************************************************************
2132  api_samr_query_usergroups
2133  ********************************************************************/
2134 static void api_samr_query_usergroups( uint16 vuid, prs_struct *data, prs_struct *rdata)
2135 {
2136         SAMR_Q_QUERY_USERGROUPS q_u;
2137         samr_io_q_query_usergroups("", &q_u, data, 0);
2138         samr_reply_query_usergroups(&q_u, rdata);
2139 }
2140
2141
2142 /*******************************************************************
2143  opens a samr alias by rid, returns a policy handle.
2144  ********************************************************************/
2145 static uint32 open_samr_alias(DOM_SID *sid, POLICY_HND *alias_pol,
2146                                 uint32 alias_rid)
2147 {
2148         BOOL pol_open = False;
2149         uint32 status = 0x0;
2150
2151         /* get a (unique) handle.  open a policy on it. */
2152         if (status == 0x0 && !(pol_open = open_lsa_policy_hnd(alias_pol)))
2153         {
2154                 status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
2155         }
2156
2157         DEBUG(0,("TODO: verify that the alias rid exists\n"));
2158
2159         /* associate a RID with the (unique) handle. */
2160         if (status == 0x0 && !set_lsa_policy_samr_rid(alias_pol, alias_rid))
2161         {
2162                 /* oh, whoops.  don't know what error message to return, here */
2163                 status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
2164         }
2165
2166         sid_append_rid(sid, alias_rid);
2167
2168         /* associate an alias SID with the (unique) handle. */
2169         if (status == 0x0 && !set_lsa_policy_samr_sid(alias_pol, sid))
2170         {
2171                 /* oh, whoops.  don't know what error message to return, here */
2172                 status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
2173         }
2174
2175         if (status != 0 && pol_open)
2176         {
2177                 close_lsa_policy_hnd(alias_pol);
2178         }
2179
2180         return status;
2181 }
2182
2183 /*******************************************************************
2184  samr_reply_create_dom_alias
2185  ********************************************************************/
2186 static void samr_reply_create_dom_alias(SAMR_Q_CREATE_DOM_ALIAS *q_u,
2187                                 prs_struct *rdata)
2188 {
2189         SAMR_R_CREATE_DOM_ALIAS r_u;
2190         DOM_SID dom_sid;
2191         LOCAL_GRP grp;
2192         POLICY_HND alias_pol;
2193         uint32 status = 0x0;
2194
2195         bzero(&alias_pol, sizeof(alias_pol));
2196
2197         DEBUG(5,("samr_create_dom_alias: %d\n", __LINE__));
2198
2199         /* find the policy handle.  open a policy on it. */
2200         if (status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->dom_pol)) == -1))
2201         {
2202                 status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
2203         }
2204
2205         /* find the domain sid */
2206         if (status == 0x0 && !get_lsa_policy_samr_sid(&q_u->dom_pol, &dom_sid))
2207         {
2208                 status = 0xC0000000 | NT_STATUS_OBJECT_TYPE_MISMATCH;
2209         }
2210
2211         if (!sid_equal(&dom_sid, &global_sam_sid))
2212         {
2213                 status = 0xC0000000 | NT_STATUS_ACCESS_DENIED;
2214         }
2215
2216         if (status == 0x0)
2217         {
2218                 unistr2_to_ascii(grp.name, &q_u->uni_acct_desc, sizeof(grp.name)-1);
2219                 fstrcpy(grp.comment, "");
2220                 grp.rid = 0xffffffff;
2221
2222                 become_root(True);
2223                 status = add_alias_entry(&grp) ? 0 : (0xC0000000 | NT_STATUS_ACCESS_DENIED);
2224                 unbecome_root(True);
2225         }
2226
2227         if (status == 0x0)
2228         {
2229                 status = open_samr_alias(&dom_sid, &alias_pol, grp.rid);
2230         }
2231
2232         /* construct the response. */
2233         make_samr_r_create_dom_alias(&r_u, &alias_pol, grp.rid, status);
2234
2235         /* store the response in the SMB stream */
2236         samr_io_r_create_dom_alias("", &r_u, rdata, 0);
2237
2238         DEBUG(5,("samr_create_dom_alias: %d\n", __LINE__));
2239
2240 }
2241
2242 /*******************************************************************
2243  api_samr_create_dom_alias
2244  ********************************************************************/
2245 static void api_samr_create_dom_alias( uint16 vuid, prs_struct *data, prs_struct *rdata)
2246 {
2247         SAMR_Q_CREATE_DOM_ALIAS q_u;
2248         samr_io_q_create_dom_alias("", &q_u, data, 0);
2249         samr_reply_create_dom_alias(&q_u, rdata);
2250 }
2251
2252
2253 /*******************************************************************
2254  opens a samr group by rid, returns a policy handle.
2255  ********************************************************************/
2256 static uint32 open_samr_group(DOM_SID *sid, POLICY_HND *group_pol,
2257                                 uint32 group_rid)
2258 {
2259         BOOL pol_open = False;
2260         uint32 status = 0x0;
2261
2262         /* get a (unique) handle.  open a policy on it. */
2263         if (status == 0x0 && !(pol_open = open_lsa_policy_hnd(group_pol)))
2264         {
2265                 status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
2266         }
2267
2268         DEBUG(0,("TODO: verify that the group rid exists\n"));
2269
2270         /* associate a RID with the (unique) handle. */
2271         if (status == 0x0 && !set_lsa_policy_samr_rid(group_pol, group_rid))
2272         {
2273                 /* oh, whoops.  don't know what error message to return, here */
2274                 status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
2275         }
2276
2277         sid_append_rid(sid, group_rid);
2278
2279         /* associate an group SID with the (unique) handle. */
2280         if (status == 0x0 && !set_lsa_policy_samr_sid(group_pol, sid))
2281         {
2282                 /* oh, whoops.  don't know what error message to return, here */
2283                 status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
2284         }
2285
2286         if (status != 0 && pol_open)
2287         {
2288                 close_lsa_policy_hnd(group_pol);
2289         }
2290
2291         return status;
2292 }
2293
2294 /*******************************************************************
2295  samr_reply_create_dom_group
2296  ********************************************************************/
2297 static void samr_reply_create_dom_group(SAMR_Q_CREATE_DOM_GROUP *q_u,
2298                                 prs_struct *rdata)
2299 {
2300         SAMR_R_CREATE_DOM_GROUP r_u;
2301         DOM_SID dom_sid;
2302         DOMAIN_GRP grp;
2303         POLICY_HND group_pol;
2304         uint32 status = 0x0;
2305
2306         bzero(&group_pol, sizeof(group_pol));
2307
2308         DEBUG(5,("samr_create_dom_group: %d\n", __LINE__));
2309
2310         /* find the policy handle.  open a policy on it. */
2311         if (status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->pol)) == -1))
2312         {
2313                 status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
2314         }
2315
2316         /* find the domain sid */
2317         if (status == 0x0 && !get_lsa_policy_samr_sid(&q_u->pol, &dom_sid))
2318         {
2319                 status = 0xC0000000 | NT_STATUS_OBJECT_TYPE_MISMATCH;
2320         }
2321
2322         if (!sid_equal(&dom_sid, &global_sam_sid))
2323         {
2324                 status = 0xC0000000 | NT_STATUS_ACCESS_DENIED;
2325         }
2326
2327         if (status == 0x0)
2328         {
2329                 unistr2_to_ascii(grp.name, &q_u->uni_acct_desc, sizeof(grp.name)-1);
2330                 fstrcpy(grp.comment, "");
2331                 grp.rid = 0xffffffff;
2332                 grp.attr = 0x07;
2333
2334                 become_root(True);
2335                 status = add_group_entry(&grp) ? 0x0 : (0xC0000000 | NT_STATUS_ACCESS_DENIED);
2336                 unbecome_root(True);
2337         }
2338
2339         if (status == 0x0)
2340         {
2341                 status = open_samr_group(&dom_sid, &group_pol, grp.rid);
2342         }
2343
2344         /* construct the response. */
2345         make_samr_r_create_dom_group(&r_u, &group_pol, grp.rid, status);
2346
2347         /* store the response in the SMB stream */
2348         samr_io_r_create_dom_group("", &r_u, rdata, 0);
2349
2350         DEBUG(5,("samr_create_dom_group: %d\n", __LINE__));
2351
2352 }
2353
2354 /*******************************************************************
2355  api_samr_create_dom_group
2356  ********************************************************************/
2357 static void api_samr_create_dom_group( uint16 vuid, prs_struct *data, prs_struct *rdata)
2358 {
2359         SAMR_Q_CREATE_DOM_GROUP q_u;
2360         samr_io_q_create_dom_group("", &q_u, data, 0);
2361         samr_reply_create_dom_group(&q_u, rdata);
2362 }
2363
2364
2365 /*******************************************************************
2366  samr_reply_query_dom_info
2367  ********************************************************************/
2368 static void samr_reply_query_dom_info(SAMR_Q_QUERY_DOMAIN_INFO *q_u,
2369                                 prs_struct *rdata)
2370 {
2371         SAMR_R_QUERY_DOMAIN_INFO r_u;
2372         SAM_UNK_CTR ctr;
2373         uint16 switch_value = 0x0;
2374         uint32 status = 0x0;
2375
2376         ZERO_STRUCT(r_u);
2377         ZERO_STRUCT(ctr);
2378
2379         r_u.ctr = &ctr;
2380
2381         DEBUG(5,("samr_reply_query_dom_info: %d\n", __LINE__));
2382
2383         /* find the policy handle.  open a policy on it. */
2384         if (r_u.status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->domain_pol)) == -1))
2385         {
2386                 r_u.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
2387                 DEBUG(5,("samr_reply_query_dom_info: invalid handle\n"));
2388         }
2389
2390         if (status == 0x0)
2391         {
2392                 switch (q_u->switch_value)
2393                 {
2394                         case 0x06:
2395                         {
2396                                 switch_value = 0x6;
2397                                 make_unk_info6(&ctr.info.inf6);
2398
2399                                 break;
2400                         }
2401                         case 0x07:
2402                         {
2403                                 switch_value = 0x7;
2404                                 make_unk_info7(&ctr.info.inf7);
2405
2406                                 break;
2407                         }
2408                         case 0x02:
2409                         {
2410                                 switch_value = 0x2;
2411                                 make_unk_info2(&ctr.info.inf2, global_sam_name, global_myname);
2412
2413                                 break;
2414                         }
2415                         case 0x01:
2416                         {
2417                                 switch_value = 0x1;
2418                                 make_unk_info1(&ctr.info.inf1);
2419
2420                                 break;
2421                         }
2422                         default:
2423                         {
2424                                 status = 0xC0000000 | NT_STATUS_INVALID_INFO_CLASS;
2425                                 break;
2426                         }
2427                 }
2428         }
2429
2430         make_samr_r_query_dom_info(&r_u, switch_value, &ctr, status);
2431
2432         /* store the response in the SMB stream */
2433         samr_io_r_query_dom_info("", &r_u, rdata, 0);
2434
2435         DEBUG(5,("samr_query_dom_info: %d\n", __LINE__));
2436
2437 }
2438
2439 /*******************************************************************
2440  api_samr_query_dom_info
2441  ********************************************************************/
2442 static void api_samr_query_dom_info( uint16 vuid, prs_struct *data, prs_struct *rdata)
2443 {
2444         SAMR_Q_QUERY_DOMAIN_INFO q_e;
2445         samr_io_q_query_dom_info("", &q_e, data, 0);
2446         samr_reply_query_dom_info(&q_e, rdata);
2447 }
2448
2449
2450
2451 /*******************************************************************
2452  samr_reply_create_user
2453  ********************************************************************/
2454 static void samr_reply_create_user(SAMR_Q_CREATE_USER *q_u,
2455                                 prs_struct *rdata)
2456 {
2457         struct sam_passwd *sam_pass;
2458         fstring user_name;
2459
2460         SAMR_R_CREATE_USER r_u;
2461         POLICY_HND pol;
2462         uint32 status = 0x0;
2463         uint32 user_rid = 0xffffffff;
2464         BOOL pol_open = False;
2465
2466         /* find the machine account: tell the caller if it exists.
2467            lkclXXXX i have *no* idea if this is a problem or not
2468            or even if you are supposed to construct a different
2469            reply if the account already exists...
2470          */
2471
2472         /* find the policy handle.  open a policy on it. */
2473         if (status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->domain_pol)) == -1))
2474         {
2475                 status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
2476         }
2477
2478         /* get a (unique) handle.  open a policy on it. */
2479         if (status == 0x0 && !(pol_open = open_lsa_policy_hnd(&pol)))
2480         {
2481                 status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
2482         }
2483
2484         unistr2_to_ascii(user_name, &q_u->uni_name, sizeof(user_name)-1);
2485
2486         sam_pass = getsam21pwntnam(user_name);
2487
2488         if (sam_pass != NULL)
2489         {
2490                 /* account exists: say so */
2491                 status = 0xC0000000 | NT_STATUS_USER_EXISTS;
2492         }
2493         else
2494         {
2495                 pstring err_str;
2496                 pstring msg_str;
2497
2498                 if (!local_password_change(user_name, True,
2499                           q_u->acb_info | ACB_DISABLED, 0xffff,
2500                           NULL,
2501                           err_str, sizeof(err_str),
2502                           msg_str, sizeof(msg_str)))
2503                 {
2504                         DEBUG(0,("%s\n", err_str));
2505                         status = 0xC0000000 | NT_STATUS_ACCESS_DENIED;
2506                 }
2507                 else
2508                 {
2509                         sam_pass = getsam21pwntnam(user_name);
2510                         if (sam_pass == NULL)
2511                         {
2512                                 /* account doesn't exist: say so */
2513                                 status = 0xC0000000 | NT_STATUS_ACCESS_DENIED;
2514                         }
2515                         else
2516                         {
2517                                 user_rid = sam_pass->user_rid;
2518                         }
2519                 }
2520         }
2521
2522         /* associate the RID with the (unique) handle. */
2523         if (status == 0x0 && !set_lsa_policy_samr_rid(&pol, user_rid))
2524         {
2525                 /* oh, whoops.  don't know what error message to return, here */
2526                 status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
2527         }
2528
2529         if (status != 0 && pol_open)
2530         {
2531                 close_lsa_policy_hnd(&pol);
2532         }
2533
2534         DEBUG(5,("samr_create_user: %d\n", __LINE__));
2535
2536         make_samr_r_create_user(&r_u, &pol, 0x000703ff, user_rid, status);
2537
2538         /* store the response in the SMB stream */
2539         samr_io_r_create_user("", &r_u, rdata, 0);
2540
2541         DEBUG(5,("samr_create_user: %d\n", __LINE__));
2542
2543 }
2544
2545 /*******************************************************************
2546  api_samr_create_user
2547  ********************************************************************/
2548 static void api_samr_create_user( uint16 vuid, prs_struct *data, prs_struct *rdata)
2549 {
2550         SAMR_Q_CREATE_USER q_u;
2551
2552         /* grab the samr unknown 32 */
2553         samr_io_q_create_user("", &q_u, data, 0);
2554
2555         /* construct reply. */
2556         samr_reply_create_user(&q_u, rdata);
2557 }
2558
2559
2560 /*******************************************************************
2561  samr_reply_connect_anon
2562  ********************************************************************/
2563 static void samr_reply_connect_anon(SAMR_Q_CONNECT_ANON *q_u,
2564                                 prs_struct *rdata)
2565 {
2566         SAMR_R_CONNECT_ANON r_u;
2567         BOOL pol_open = False;
2568
2569         /* set up the SAMR connect_anon response */
2570
2571         r_u.status = 0x0;
2572         /* get a (unique) handle.  open a policy on it. */
2573         if (r_u.status == 0x0 && !(pol_open = open_lsa_policy_hnd(&(r_u.connect_pol))))
2574         {
2575                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
2576         }
2577
2578         /* associate the domain SID with the (unique) handle. */
2579         if (r_u.status == 0x0 && !set_lsa_policy_samr_pol_status(&(r_u.connect_pol), q_u->unknown_0))
2580         {
2581                 /* oh, whoops.  don't know what error message to return, here */
2582                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
2583         }
2584
2585         if (r_u.status != 0 && pol_open)
2586         {
2587                 close_lsa_policy_hnd(&(r_u.connect_pol));
2588         }
2589
2590         DEBUG(5,("samr_connect_anon: %d\n", __LINE__));
2591
2592         /* store the response in the SMB stream */
2593         samr_io_r_connect_anon("", &r_u, rdata, 0);
2594
2595         DEBUG(5,("samr_connect_anon: %d\n", __LINE__));
2596
2597 }
2598
2599 /*******************************************************************
2600  api_samr_connect_anon
2601  ********************************************************************/
2602 static void api_samr_connect_anon( uint16 vuid, prs_struct *data, prs_struct *rdata)
2603 {
2604         SAMR_Q_CONNECT_ANON q_u;
2605         samr_io_q_connect_anon("", &q_u, data, 0);
2606         samr_reply_connect_anon(&q_u, rdata);
2607 }
2608
2609 /*******************************************************************
2610  samr_reply_connect
2611  ********************************************************************/
2612 static void samr_reply_connect(SAMR_Q_CONNECT *q_u,
2613                                 prs_struct *rdata)
2614 {
2615         SAMR_R_CONNECT r_u;
2616         BOOL pol_open = False;
2617
2618         /* set up the SAMR connect response */
2619
2620         r_u.status = 0x0;
2621         /* get a (unique) handle.  open a policy on it. */
2622         if (r_u.status == 0x0 && !(pol_open = open_lsa_policy_hnd(&(r_u.connect_pol))))
2623         {
2624                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
2625         }
2626
2627         /* associate the domain SID with the (unique) handle. */
2628         if (r_u.status == 0x0 && !set_lsa_policy_samr_pol_status(&(r_u.connect_pol), q_u->unknown_0))
2629         {
2630                 /* oh, whoops.  don't know what error message to return, here */
2631                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
2632         }
2633
2634         if (r_u.status != 0 && pol_open)
2635         {
2636                 close_lsa_policy_hnd(&(r_u.connect_pol));
2637         }
2638
2639         DEBUG(5,("samr_connect: %d\n", __LINE__));
2640
2641         /* store the response in the SMB stream */
2642         samr_io_r_connect("", &r_u, rdata, 0);
2643
2644         DEBUG(5,("samr_connect: %d\n", __LINE__));
2645
2646 }
2647
2648 /*******************************************************************
2649  api_samr_connect
2650  ********************************************************************/
2651 static void api_samr_connect( uint16 vuid, prs_struct *data, prs_struct *rdata)
2652 {
2653         SAMR_Q_CONNECT q_u;
2654         samr_io_q_connect("", &q_u, data, 0);
2655         samr_reply_connect(&q_u, rdata);
2656 }
2657
2658 /*******************************************************************
2659  samr_reply_open_alias
2660  ********************************************************************/
2661 static void samr_reply_open_alias(SAMR_Q_OPEN_ALIAS *q_u,
2662                                 prs_struct *rdata)
2663 {
2664         SAMR_R_OPEN_ALIAS r_u;
2665         DOM_SID sid;
2666         BOOL pol_open = False;
2667
2668         /* set up the SAMR open_alias response */
2669
2670         r_u.status = 0x0;
2671         if (r_u.status == 0x0 && !get_lsa_policy_samr_sid(&q_u->dom_pol, &sid))
2672         {
2673                 r_u.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
2674         }
2675
2676         /* get a (unique) handle.  open a policy on it. */
2677         if (r_u.status == 0x0 && !(pol_open = open_lsa_policy_hnd(&(r_u.pol))))
2678         {
2679                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
2680         }
2681
2682         DEBUG(0,("TODO: verify that the alias rid exists\n"));
2683
2684         /* associate a RID with the (unique) handle. */
2685         if (r_u.status == 0x0 && !set_lsa_policy_samr_rid(&(r_u.pol), q_u->rid_alias))
2686         {
2687                 /* oh, whoops.  don't know what error message to return, here */
2688                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
2689         }
2690
2691         sid_append_rid(&sid, q_u->rid_alias);
2692
2693         /* associate an alias SID with the (unique) handle. */
2694         if (r_u.status == 0x0 && !set_lsa_policy_samr_sid(&(r_u.pol), &sid))
2695         {
2696                 /* oh, whoops.  don't know what error message to return, here */
2697                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
2698         }
2699
2700         if (r_u.status != 0 && pol_open)
2701         {
2702                 close_lsa_policy_hnd(&(r_u.pol));
2703         }
2704
2705         DEBUG(5,("samr_open_alias: %d\n", __LINE__));
2706
2707         /* store the response in the SMB stream */
2708         samr_io_r_open_alias("", &r_u, rdata, 0);
2709
2710         DEBUG(5,("samr_open_alias: %d\n", __LINE__));
2711
2712 }
2713
2714 /*******************************************************************
2715  api_samr_open_alias
2716  ********************************************************************/
2717 static void api_samr_open_alias( uint16 vuid, prs_struct *data, prs_struct *rdata)
2718                                 
2719 {
2720         SAMR_Q_OPEN_ALIAS q_u;
2721         samr_io_q_open_alias("", &q_u, data, 0);
2722         samr_reply_open_alias(&q_u, rdata);
2723 }
2724
2725 /*******************************************************************
2726  samr_reply_open_group
2727  ********************************************************************/
2728 static void samr_reply_open_group(SAMR_Q_OPEN_GROUP *q_u,
2729                                 prs_struct *rdata)
2730 {
2731         SAMR_R_OPEN_GROUP r_u;
2732         DOM_SID sid;
2733
2734         DEBUG(5,("samr_open_group: %d\n", __LINE__));
2735
2736         r_u.status = 0x0;
2737
2738         /* find the domain sid associated with the policy handle */
2739         if (r_u.status == 0x0 && !get_lsa_policy_samr_sid(&q_u->domain_pol, &sid))
2740         {
2741                 r_u.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
2742         }
2743
2744         if (r_u.status == 0x0 && !sid_equal(&sid, &global_sam_sid))
2745         {
2746                 r_u.status = 0xC0000000 | NT_STATUS_ACCESS_DENIED;
2747         }
2748
2749         if (r_u.status == 0x0)
2750         {
2751                 r_u.status = open_samr_group(&sid, &r_u.pol, q_u->rid_group);
2752         }
2753
2754         /* store the response in the SMB stream */
2755         samr_io_r_open_group("", &r_u, rdata, 0);
2756
2757         DEBUG(5,("samr_open_group: %d\n", __LINE__));
2758
2759 }
2760
2761 /*******************************************************************
2762  api_samr_open_group
2763  ********************************************************************/
2764 static void api_samr_open_group( uint16 vuid, prs_struct *data, prs_struct *rdata)
2765                                 
2766 {
2767         SAMR_Q_OPEN_GROUP q_u;
2768         samr_io_q_open_group("", &q_u, data, 0);
2769         samr_reply_open_group(&q_u, rdata);
2770 }
2771
2772 /*******************************************************************
2773  samr_reply_lookup_domain
2774  ********************************************************************/
2775 static void samr_reply_lookup_domain(SAMR_Q_LOOKUP_DOMAIN *q_u,
2776                                 prs_struct *rdata)
2777 {
2778         SAMR_R_LOOKUP_DOMAIN r_u;
2779         fstring domain;
2780
2781         DEBUG(5,("samr_lookup_domain: %d\n", __LINE__));
2782
2783         r_u.ptr_sid = 0;
2784         r_u.status = 0x0;
2785
2786         /* find the connection policy handle */
2787         if (find_lsa_policy_by_hnd(&(q_u->connect_pol)) == -1)
2788         {
2789                 r_u.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
2790         }
2791
2792         if (r_u.status == 0x0)
2793         {
2794                 unistr2_to_ascii(domain, &(q_u->uni_domain), sizeof(domain));
2795                 DEBUG(5, ("Lookup Domain: %s\n", domain));
2796
2797                 /* check it's one of ours */
2798                 if (strequal(domain, global_sam_name))
2799                 {
2800                         make_dom_sid2(&(r_u.dom_sid), &global_sam_sid);
2801                         r_u.ptr_sid = 1;
2802                 }
2803                 else if (strequal(domain, "BUILTIN"))
2804                 {
2805                         make_dom_sid2(&(r_u.dom_sid), &global_sid_S_1_5_20);
2806                         r_u.ptr_sid = 1;
2807                 }
2808                 else
2809                 {
2810                         r_u.status = 0xC0000000 | NT_STATUS_NO_SUCH_DOMAIN;
2811                 }
2812         }
2813
2814         /* store the response in the SMB stream */
2815         samr_io_r_lookup_domain("", &r_u, rdata, 0);
2816
2817         DEBUG(5,("samr_lookup_domain: %d\n", __LINE__));
2818 }
2819
2820 /*******************************************************************
2821  api_samr_lookup_domain
2822  ********************************************************************/
2823 static void api_samr_lookup_domain( uint16 vuid, prs_struct *data, prs_struct *rdata)
2824 {
2825         SAMR_Q_LOOKUP_DOMAIN q_u;
2826         samr_io_q_lookup_domain("", &q_u, data, 0);
2827         samr_reply_lookup_domain(&q_u, rdata);
2828 }
2829
2830 /*******************************************************************
2831  array of \PIPE\samr operations
2832  ********************************************************************/
2833 static struct api_struct api_samr_cmds [] =
2834 {
2835         { "SAMR_CLOSE_HND"        , SAMR_CLOSE_HND        , api_samr_close_hnd        },
2836         { "SAMR_CONNECT"          , SAMR_CONNECT          , api_samr_connect          },
2837         { "SAMR_CONNECT_ANON"     , SAMR_CONNECT_ANON     , api_samr_connect_anon     },
2838         { "SAMR_ENUM_DOM_USERS"   , SAMR_ENUM_DOM_USERS   , api_samr_enum_dom_users   },
2839         { "SAMR_ENUM_DOM_GROUPS"  , SAMR_ENUM_DOM_GROUPS  , api_samr_enum_dom_groups  },
2840         { "SAMR_ENUM_DOM_ALIASES" , SAMR_ENUM_DOM_ALIASES , api_samr_enum_dom_aliases },
2841         { "SAMR_QUERY_USERALIASES", SAMR_QUERY_USERALIASES, api_samr_query_useraliases},
2842         { "SAMR_QUERY_ALIASMEM"   , SAMR_QUERY_ALIASMEM   , api_samr_query_aliasmem   },
2843         { "SAMR_QUERY_GROUPMEM"   , SAMR_QUERY_GROUPMEM   , api_samr_query_groupmem   },
2844         { "SAMR_ADD_ALIASMEM"     , SAMR_ADD_ALIASMEM     , api_samr_add_aliasmem     },
2845         { "SAMR_DEL_ALIASMEM"     , SAMR_DEL_ALIASMEM     , api_samr_del_aliasmem     },
2846         { "SAMR_ADD_GROUPMEM"     , SAMR_ADD_GROUPMEM     , api_samr_add_groupmem     },
2847         { "SAMR_DEL_GROUPMEM"     , SAMR_DEL_GROUPMEM     , api_samr_del_groupmem     },
2848         { "SAMR_DELETE_DOM_GROUP" , SAMR_DELETE_DOM_GROUP , api_samr_delete_dom_group },
2849         { "SAMR_DELETE_DOM_ALIAS" , SAMR_DELETE_DOM_ALIAS , api_samr_delete_dom_alias },
2850         { "SAMR_CREATE_DOM_GROUP" , SAMR_CREATE_DOM_GROUP , api_samr_create_dom_group },
2851         { "SAMR_CREATE_DOM_ALIAS" , SAMR_CREATE_DOM_ALIAS , api_samr_create_dom_alias },
2852         { "SAMR_LOOKUP_NAMES"     , SAMR_LOOKUP_NAMES     , api_samr_lookup_names     },
2853         { "SAMR_OPEN_USER"        , SAMR_OPEN_USER        , api_samr_open_user        },
2854         { "SAMR_QUERY_USERINFO"   , SAMR_QUERY_USERINFO   , api_samr_query_userinfo   },
2855         { "SAMR_SET_USERINFO"     , SAMR_SET_USERINFO     , api_samr_set_userinfo     },
2856         { "SAMR_QUERY_DOMAIN_INFO", SAMR_QUERY_DOMAIN_INFO, api_samr_query_dom_info   },
2857         { "SAMR_QUERY_USERGROUPS" , SAMR_QUERY_USERGROUPS , api_samr_query_usergroups },
2858         { "SAMR_QUERY_DISPINFO"   , SAMR_QUERY_DISPINFO   , api_samr_query_dispinfo   },
2859         { "SAMR_QUERY_DISPINFO3"  , SAMR_QUERY_DISPINFO3  , api_samr_query_dispinfo   },
2860         { "SAMR_QUERY_DISPINFO4"  , SAMR_QUERY_DISPINFO4  , api_samr_query_dispinfo   },
2861         { "SAMR_QUERY_ALIASINFO"  , SAMR_QUERY_ALIASINFO  , api_samr_query_aliasinfo  },
2862         { "SAMR_QUERY_GROUPINFO"  , SAMR_QUERY_GROUPINFO  , api_samr_query_groupinfo  },
2863         { "SAMR_CREATE_USER"      , SAMR_CREATE_USER      , api_samr_create_user      },
2864         { "SAMR_LOOKUP_RIDS"      , SAMR_LOOKUP_RIDS      , api_samr_lookup_rids      },
2865         { "SAMR_UNKNOWN_38"       , SAMR_UNKNOWN_38       , api_samr_unknown_38       },
2866         { "SAMR_CHGPASSWD_USER"   , SAMR_CHGPASSWD_USER   , api_samr_chgpasswd_user   },
2867         { "SAMR_OPEN_ALIAS"       , SAMR_OPEN_ALIAS       , api_samr_open_alias       },
2868         { "SAMR_OPEN_GROUP"       , SAMR_OPEN_GROUP       , api_samr_open_group       },
2869         { "SAMR_OPEN_DOMAIN"      , SAMR_OPEN_DOMAIN      , api_samr_open_domain      },
2870         { "SAMR_LOOKUP_DOMAIN"    , SAMR_LOOKUP_DOMAIN    , api_samr_lookup_domain    },
2871         { "SAMR_UNKNOWN_3"        , SAMR_UNKNOWN_3        , api_samr_unknown_3        },
2872         { "SAMR_UNKNOWN_2C"       , SAMR_UNKNOWN_2C       , api_samr_unknown_2c       },
2873         { NULL                    , 0                     , NULL                      }
2874 };
2875
2876 /*******************************************************************
2877  receives a samr pipe and responds.
2878  ********************************************************************/
2879 BOOL api_samr_rpc(pipes_struct *p, prs_struct *data)
2880 {
2881     return api_rpcTNP(p, "api_samr_rpc", api_samr_cmds, data);
2882 }
2883