a6f936fecafeb8c1c352ffcc9b9ee9b243bfdcf5
[kai/samba.git] / source3 / rpc_server / srv_samr_nt.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *  Copyright (C) Andrew Tridgell              1992-1997,
5  *  Copyright (C) Luke Kenneth Casson Leighton 1996-1997,
6  *  Copyright (C) Paul Ashton                       1997.
7  *  Copyright (C) Marc Jacobsen                     1999.
8  *  Copyright (C) Jeremy Allison               2001-2002.
9  *  Copyright (C) Jean Fran├žois Micouleau      1998-2001.
10  *
11  *  This program is free software; you can redistribute it and/or modify
12  *  it under the terms of the GNU General Public License as published by
13  *  the Free Software Foundation; either version 2 of the License, or
14  *  (at your option) any later version.
15  *
16  *  This program is distributed in the hope that it will be useful,
17  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  *  GNU General Public License for more details.
20  *
21  *  You should have received a copy of the GNU General Public License
22  *  along with this program; if not, write to the Free Software
23  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24  */
25
26 /*
27  * This is the implementation of the SAMR code.
28  */
29
30 #include "includes.h"
31
32 extern fstring global_myworkgroup;
33 extern pstring global_myname;
34 extern DOM_SID global_sid_Builtin;
35
36 extern rid_name domain_group_rids[];
37 extern rid_name domain_alias_rids[];
38 extern rid_name builtin_alias_rids[];
39
40
41 typedef struct _disp_info {
42         BOOL user_dbloaded;
43         uint32 num_user_account;
44         DISP_USER_INFO *disp_user_info;
45         BOOL group_dbloaded;
46         uint32 num_group_account;
47         DISP_GROUP_INFO *disp_group_info;
48 } DISP_INFO;
49
50 struct samr_info {
51         /* for use by the \PIPE\samr policy */
52         DOM_SID sid;
53         uint32 status; /* some sort of flag.  best to record it.  comes from opnum 0x39 */
54         DISP_INFO disp_info;
55
56         TALLOC_CTX *mem_ctx;
57 };
58
59 /*******************************************************************
60  Create a samr_info struct.
61 ********************************************************************/
62
63 static struct samr_info *get_samr_info_by_sid(DOM_SID *psid)
64 {
65         struct samr_info *info;
66         fstring sid_str;
67         TALLOC_CTX *mem_ctx;
68         
69         if (psid) {
70                 sid_to_string(sid_str, psid);
71         } else {
72                 fstrcpy(sid_str,"(NULL)");
73         }
74
75         mem_ctx = talloc_init_named("samr_info for domain sid %s", sid_str);
76
77         if ((info = (struct samr_info *)talloc(mem_ctx, sizeof(struct samr_info))) == NULL)
78                 return NULL;
79
80         ZERO_STRUCTP(info);
81         DEBUG(10,("get_samr_info_by_sid: created new info for sid %s\n", sid_str));
82         if (psid) {
83                 sid_copy( &info->sid, psid);
84         } else {
85                 DEBUG(10,("get_samr_info_by_sid: created new info for NULL sid.\n"));
86         }
87         info->mem_ctx = mem_ctx;
88         return info;
89 }
90
91 /*******************************************************************
92  Function to free the per handle data.
93  ********************************************************************/
94 static void free_samr_db(struct samr_info *info)
95 {
96         int i;
97
98         /* Groups are talloced */
99
100         if (info->disp_info.user_dbloaded){
101                 for (i=0; i<info->disp_info.num_user_account; i++) {
102                         /* Not really a free, actually a 'clear' */
103                         pdb_free_sam(&info->disp_info.disp_user_info[i].sam);
104                 }
105         }
106
107         info->disp_info.user_dbloaded=False;
108         info->disp_info.group_dbloaded=False;
109         info->disp_info.num_group_account=0;
110         info->disp_info.num_user_account=0;
111 }
112
113
114 static void free_samr_info(void *ptr)
115 {
116         struct samr_info *info=(struct samr_info *) ptr;
117
118         free_samr_db(info);
119         talloc_destroy(info->mem_ctx);
120 }
121
122 /*******************************************************************
123  Ensure password info is never given out. Paranioa... JRA.
124  ********************************************************************/
125
126 static void samr_clear_passwd_fields( SAM_USER_INFO_21 *pass, int num_entries)
127 {
128         int i;
129
130         if (!pass)
131                 return;
132
133         for (i = 0; i < num_entries; i++) {
134                 memset(&pass[i].lm_pwd, '\0', sizeof(pass[i].lm_pwd));
135                 memset(&pass[i].nt_pwd, '\0', sizeof(pass[i].nt_pwd));
136         }
137 }
138
139 static void samr_clear_sam_passwd(SAM_ACCOUNT *sam_pass)
140 {
141         
142         if (!sam_pass)
143                 return;
144
145         /* These now zero out the old password */
146
147         pdb_set_lanman_passwd(sam_pass, NULL);
148         pdb_set_nt_passwd(sam_pass, NULL);
149 }
150
151
152 static NTSTATUS load_sampwd_entries(struct samr_info *info, uint16 acb_mask)
153 {
154         SAM_ACCOUNT *pwd = NULL;
155         DISP_USER_INFO *pwd_array = NULL;
156         NTSTATUS nt_status = NT_STATUS_OK;
157         TALLOC_CTX *mem_ctx = info->mem_ctx;
158
159         DEBUG(10,("load_sampwd_entries\n"));
160
161         /* if the snapshoot is already loaded, return */
162         if (info->disp_info.user_dbloaded==True) {
163                 DEBUG(10,("load_sampwd_entries: already in memory\n"));
164                 return NT_STATUS_OK;
165         }
166
167         if (!pdb_setsampwent(False)) {
168                 DEBUG(0, ("load_sampwd_entries: Unable to open passdb.\n"));
169                 return NT_STATUS_ACCESS_DENIED;
170         }
171
172         for (; (NT_STATUS_IS_OK(nt_status = pdb_init_sam_talloc(mem_ctx, &pwd))) 
173                      && pdb_getsampwent(pwd) == True; pwd=NULL) {
174                 
175                 if (acb_mask != 0 && !(pdb_get_acct_ctrl(pwd) & acb_mask)) {
176                         pdb_free_sam(&pwd);
177                         DEBUG(5,(" acb_mask %x reject\n", acb_mask));
178                         continue;
179                 }
180
181                 /* Realloc some memory for the array of ptr to the SAM_ACCOUNT structs */
182                 if (info->disp_info.num_user_account % MAX_SAM_ENTRIES == 0) {
183                 
184                         DEBUG(10,("load_sampwd_entries: allocating more memory\n"));
185                         pwd_array=(DISP_USER_INFO *)talloc_realloc(mem_ctx, info->disp_info.disp_user_info, 
186                                           (info->disp_info.num_user_account+MAX_SAM_ENTRIES)*sizeof(DISP_USER_INFO));
187
188                         if (pwd_array==NULL)
189                                 return NT_STATUS_NO_MEMORY;
190
191                         info->disp_info.disp_user_info=pwd_array;
192                 }
193         
194                 /* link the SAM_ACCOUNT to the array */
195                 info->disp_info.disp_user_info[info->disp_info.num_user_account].sam=pwd;
196
197                 DEBUG(10,("load_sampwd_entries: entry: %d\n", info->disp_info.num_user_account));
198
199                 info->disp_info.num_user_account++;     
200         }
201
202         pdb_endsampwent();
203
204         /* the snapshoot is in memory, we're ready to enumerate fast */
205
206         info->disp_info.user_dbloaded=True;
207
208         DEBUG(12,("load_sampwd_entries: done\n"));
209
210         return nt_status;
211 }
212
213 static NTSTATUS load_group_domain_entries(struct samr_info *info, DOM_SID *sid)
214 {
215         GROUP_MAP *map=NULL;
216         DISP_GROUP_INFO *grp_array = NULL;
217         uint32 group_entries = 0;
218         uint32 i;
219         TALLOC_CTX *mem_ctx = info->mem_ctx;
220
221         DEBUG(10,("load_group_domain_entries\n"));
222
223         /* if the snapshoot is already loaded, return */
224         if (info->disp_info.group_dbloaded==True) {
225                 DEBUG(10,("load_group_domain_entries: already in memory\n"));
226                 return NT_STATUS_OK;
227         }
228
229         if (!enum_group_mapping(SID_NAME_DOM_GRP, &map, (int *)&group_entries, ENUM_ONLY_MAPPED, MAPPING_WITHOUT_PRIV)) {
230                 return NT_STATUS_NO_MEMORY;
231         }
232
233         info->disp_info.num_group_account=group_entries;
234
235         grp_array=(DISP_GROUP_INFO *)talloc(mem_ctx, info->disp_info.num_group_account*sizeof(DISP_GROUP_INFO));
236
237         if (group_entries!=0 && grp_array==NULL) {
238                 SAFE_FREE(map);
239                 return NT_STATUS_NO_MEMORY;
240         }
241
242         info->disp_info.disp_group_info=grp_array;
243
244         for (i=0; i<group_entries; i++) {
245         
246                 grp_array[i].grp=(DOMAIN_GRP *)talloc(mem_ctx, sizeof(DOMAIN_GRP));
247         
248                 fstrcpy(grp_array[i].grp->name, map[i].nt_name);
249                 fstrcpy(grp_array[i].grp->comment, map[i].comment);
250                 sid_split_rid(&map[i].sid, &grp_array[i].grp->rid);
251                 grp_array[i].grp->attr=SID_NAME_DOM_GRP;
252         }
253
254         SAFE_FREE(map);
255
256         /* the snapshoot is in memory, we're ready to enumerate fast */
257
258         info->disp_info.group_dbloaded=True;
259
260         DEBUG(12,("load_group_domain_entries: done\n"));
261
262         return NT_STATUS_OK;
263 }
264
265
266 /*******************************************************************
267   This next function should be replaced with something that
268   dynamically returns the correct user info..... JRA.
269  ********************************************************************/
270
271 static NTSTATUS get_sampwd_entries(SAM_USER_INFO_21 *pw_buf, int start_idx,
272                                 int *total_entries, int *num_entries,
273                                 int max_num_entries, uint16 acb_mask)
274 {
275         SAM_ACCOUNT *pwd = NULL;
276         BOOL not_finished = True;
277         NTSTATUS nt_status;
278
279         (*num_entries) = 0;
280         (*total_entries) = 0;
281
282         if (pw_buf == NULL)
283                 return NT_STATUS_NO_MEMORY;
284
285         if (!NT_STATUS_IS_OK(nt_status = pdb_init_sam(&pwd))) {
286                 return nt_status;
287         }
288
289         if (!pdb_setsampwent(False)) {
290                 DEBUG(0, ("get_sampwd_entries: Unable to open passdb.\n"));
291                 pdb_free_sam(&pwd);
292                 return NT_STATUS_ACCESS_DENIED;
293         }
294         
295         while (((not_finished = pdb_getsampwent(pwd)) != False) 
296                && (*num_entries) < max_num_entries) 
297         {
298                 int user_name_len;
299                 const char *user_name;
300
301                 if (start_idx > 0) {
302
303                         pdb_free_sam(&pwd);
304                         
305                         if (!NT_STATUS_IS_OK(nt_status = pdb_init_sam(&pwd))) {
306                                 pdb_endsampwent();
307                                 return nt_status;
308                         }
309
310                         /* skip the requested number of entries.
311                            not very efficient, but hey...  */
312                         start_idx--;
313                         continue;
314                 }
315                 
316                 user_name = pdb_get_username(pwd);
317
318                 if (!user_name) {
319                         DEBUG(2, ("account had NULL username!\n"));
320                 } else if (!(acb_mask == 0 || (pdb_get_acct_ctrl(pwd) & acb_mask))) {
321                         DEBUG(5,(" acb_mask %x rejects\n", acb_mask));
322                 } else {
323                         DEBUG(5,(" acb_mask %x accepts\n", acb_mask));
324                         
325                         user_name_len = strlen(user_name)+1;
326                         init_unistr2(&pw_buf[(*num_entries)].uni_user_name, user_name, user_name_len);
327                         init_uni_hdr(&pw_buf[(*num_entries)].hdr_user_name, user_name_len);
328                         pw_buf[(*num_entries)].user_rid = pdb_get_user_rid(pwd);
329                         memset((char *)pw_buf[(*num_entries)].nt_pwd, '\0', 16);
330                         
331                         /* Now check if the NT compatible password is available. */
332                         if (pdb_get_nt_passwd(pwd))
333                                 memcpy( pw_buf[(*num_entries)].nt_pwd , pdb_get_nt_passwd(pwd), 16);
334                         
335                         pw_buf[(*num_entries)].acb_info = pdb_get_acct_ctrl(pwd);
336                         
337                         DEBUG(5, ("entry idx: %d user %s, rid 0x%x, acb %x",
338                                   (*num_entries), pdb_get_username(pwd), pdb_get_user_rid(pwd), pdb_get_acct_ctrl(pwd) ));
339                         
340                         (*num_entries)++;
341                 }
342
343                 (*total_entries)++;
344                 
345                 pdb_free_sam(&pwd);
346
347                 if (!NT_STATUS_IS_OK(nt_status = pdb_init_sam(&pwd))) {
348                         pdb_endsampwent();
349                         return nt_status;
350                 }
351
352         }
353         
354         pdb_endsampwent();
355         pdb_free_sam(&pwd);
356
357         if (not_finished)
358                 return STATUS_MORE_ENTRIES;
359         else
360                 return NT_STATUS_OK;
361 }
362
363 /*******************************************************************
364  _samr_close_hnd
365  ********************************************************************/
366
367 NTSTATUS _samr_close_hnd(pipes_struct *p, SAMR_Q_CLOSE_HND *q_u, SAMR_R_CLOSE_HND *r_u)
368 {
369         r_u->status = NT_STATUS_OK;
370
371         /* close the policy handle */
372         if (!close_policy_hnd(p, &q_u->pol))
373                 return NT_STATUS_OBJECT_NAME_INVALID;
374
375         DEBUG(5,("samr_reply_close_hnd: %d\n", __LINE__));
376
377         return r_u->status;
378 }
379
380 /*******************************************************************
381  samr_reply_open_domain
382  ********************************************************************/
383
384 NTSTATUS _samr_open_domain(pipes_struct *p, SAMR_Q_OPEN_DOMAIN *q_u, SAMR_R_OPEN_DOMAIN *r_u)
385 {
386         struct samr_info *info;
387
388         r_u->status = NT_STATUS_OK;
389
390         /* find the connection policy handle. */
391         if (!find_policy_by_hnd(p, &q_u->pol, NULL))
392                 return NT_STATUS_INVALID_HANDLE;
393
394         /* associate the domain SID with the (unique) handle. */
395         if ((info = get_samr_info_by_sid(&q_u->dom_sid.sid))==NULL)
396                 return NT_STATUS_NO_MEMORY;
397
398         /* get a (unique) handle.  open a policy on it. */
399         if (!create_policy_hnd(p, &r_u->domain_pol, free_samr_info, (void *)info))
400                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
401
402         DEBUG(5,("samr_open_domain: %d\n", __LINE__));
403
404         return r_u->status;
405 }
406
407 /*******************************************************************
408  _samr_get_usrdom_pwinfo
409  ********************************************************************/
410
411 NTSTATUS _samr_get_usrdom_pwinfo(pipes_struct *p, SAMR_Q_GET_USRDOM_PWINFO *q_u, SAMR_R_GET_USRDOM_PWINFO *r_u)
412 {
413         struct samr_info *info = NULL;
414
415         r_u->status = NT_STATUS_OK;
416
417         /* find the policy handle.  open a policy on it. */
418         if (!find_policy_by_hnd(p, &q_u->user_pol, (void **)&info))
419                 return NT_STATUS_INVALID_HANDLE;
420
421         if (!sid_check_is_in_our_domain(&info->sid))
422                 return NT_STATUS_OBJECT_TYPE_MISMATCH;
423
424         init_samr_r_get_usrdom_pwinfo(r_u, NT_STATUS_OK);
425
426         DEBUG(5,("_samr_get_usrdom_pwinfo: %d\n", __LINE__));
427
428         /* 
429          * NT sometimes return NT_STATUS_ACCESS_DENIED
430          * I don't know yet why.
431          */
432
433         return r_u->status;
434 }
435
436 /*******************************************************************
437  samr_make_usr_obj_sd
438  ********************************************************************/
439
440 static NTSTATUS samr_make_usr_obj_sd(TALLOC_CTX *ctx, SEC_DESC_BUF **buf, DOM_SID *usr_sid)
441 {
442         extern DOM_SID global_sid_World;
443         DOM_SID adm_sid;
444         DOM_SID act_sid;
445
446         SEC_ACE ace[4];
447         SEC_ACCESS mask;
448
449         SEC_ACL *psa = NULL;
450         SEC_DESC *psd = NULL;
451         size_t sd_size;
452
453         sid_copy(&adm_sid, &global_sid_Builtin);
454         sid_append_rid(&adm_sid, BUILTIN_ALIAS_RID_ADMINS);
455
456         sid_copy(&act_sid, &global_sid_Builtin);
457         sid_append_rid(&act_sid, BUILTIN_ALIAS_RID_ACCOUNT_OPS);
458
459         init_sec_access(&mask, 0x2035b);
460         init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
461
462         init_sec_access(&mask, 0xf07ff);
463         init_sec_ace(&ace[1], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
464         init_sec_ace(&ace[2], &act_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
465
466         init_sec_access(&mask,0x20044);
467         init_sec_ace(&ace[3], usr_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
468
469         if((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 4, ace)) == NULL)
470                 return NT_STATUS_NO_MEMORY;
471
472         if((psd = make_sec_desc(ctx, SEC_DESC_REVISION, NULL, NULL, NULL, psa, &sd_size)) == NULL)
473                 return NT_STATUS_NO_MEMORY;
474
475         if((*buf = make_sec_desc_buf(ctx, sd_size, psd)) == NULL)
476                 return NT_STATUS_NO_MEMORY;
477
478         return NT_STATUS_OK;
479 }
480
481 static BOOL get_lsa_policy_samr_sid(pipes_struct *p, POLICY_HND *pol, DOM_SID *sid)
482 {
483         struct samr_info *info = NULL;
484
485         /* find the policy handle.  open a policy on it. */
486         if (!find_policy_by_hnd(p, pol, (void **)&info))
487                 return False;
488
489         if (!info)
490                 return False;
491
492         *sid = info->sid;
493         return True;
494 }
495
496 /*******************************************************************
497  _samr_query_sec_obj
498  ********************************************************************/
499
500 NTSTATUS _samr_query_sec_obj(pipes_struct *p, SAMR_Q_QUERY_SEC_OBJ *q_u, SAMR_R_QUERY_SEC_OBJ *r_u)
501 {
502         DOM_SID pol_sid;
503         fstring str_sid;
504
505         r_u->status = NT_STATUS_OK;
506
507         /* Get the SID. */
508
509         if (!get_lsa_policy_samr_sid(p, &q_u->user_pol, &pol_sid))
510                 return NT_STATUS_INVALID_HANDLE;
511
512         DEBUG(10,("_samr_query_sec_obj: querying security on SID: %s\n", sid_to_string(str_sid, &pol_sid)));
513
514         r_u->status = samr_make_usr_obj_sd(p->mem_ctx, &r_u->buf, &pol_sid);
515
516         if (NT_STATUS_IS_OK(r_u->status))
517                 r_u->ptr = 1;
518
519         return r_u->status;
520 }
521
522 /*******************************************************************
523 makes a SAM_ENTRY / UNISTR2* structure from a user list.
524 ********************************************************************/
525
526 static void make_user_sam_entry_list(TALLOC_CTX *ctx, SAM_ENTRY **sam_pp, UNISTR2 **uni_name_pp,
527                 uint32 num_sam_entries, SAM_USER_INFO_21 *pass)
528 {
529         uint32 i;
530         SAM_ENTRY *sam;
531         UNISTR2 *uni_name;
532
533         *sam_pp = NULL;
534         *uni_name_pp = NULL;
535
536         if (num_sam_entries == 0)
537                 return;
538
539         sam = (SAM_ENTRY *)talloc_zero(ctx, sizeof(SAM_ENTRY)*num_sam_entries);
540
541         uni_name = (UNISTR2 *)talloc_zero(ctx, sizeof(UNISTR2)*num_sam_entries);
542
543         if (sam == NULL || uni_name == NULL) {
544                 DEBUG(0, ("NULL pointers in SAMR_R_QUERY_DISPINFO\n"));
545                 return;
546         }
547
548         ZERO_STRUCTP(sam);
549         ZERO_STRUCTP(uni_name);
550
551         for (i = 0; i < num_sam_entries; i++) {
552                 int len = pass[i].uni_user_name.uni_str_len;
553
554                 init_sam_entry(&sam[i], len, pass[i].user_rid);
555                 copy_unistr2(&uni_name[i], &pass[i].uni_user_name);
556         }
557
558         *sam_pp = sam;
559         *uni_name_pp = uni_name;
560 }
561
562 /*******************************************************************
563  samr_reply_enum_dom_users
564  ********************************************************************/
565
566 NTSTATUS _samr_enum_dom_users(pipes_struct *p, SAMR_Q_ENUM_DOM_USERS *q_u, SAMR_R_ENUM_DOM_USERS *r_u)
567 {
568         SAM_USER_INFO_21 pass[MAX_SAM_ENTRIES];
569         int num_entries = 0;
570         int total_entries = 0;
571         
572         r_u->status = NT_STATUS_OK;
573
574         /* find the policy handle.  open a policy on it. */
575         if (!find_policy_by_hnd(p, &q_u->pol, NULL))
576                 return NT_STATUS_INVALID_HANDLE;
577
578         DEBUG(5,("_samr_enum_dom_users: %d\n", __LINE__));
579
580         become_root();
581         r_u->status = get_sampwd_entries(pass, q_u->start_idx, &total_entries, &num_entries,
582                                                                 MAX_SAM_ENTRIES, q_u->acb_mask);
583         unbecome_root();
584
585         if (NT_STATUS_IS_ERR(r_u->status))
586                 return r_u->status;
587
588         samr_clear_passwd_fields(pass, num_entries);
589
590         /* 
591          * Note from JRA. total_entries is not being used here. Currently if there is a
592          * large user base then it looks like NT will enumerate until get_sampwd_entries
593          * returns False due to num_entries being zero. This will cause an access denied
594          * return. I don't think this is right and needs further investigation. Note that
595          * this is also the same in the TNG code (I don't think that has been tested with
596          * a very large user list as MAX_SAM_ENTRIES is set to 600).
597          * 
598          * I also think that one of the 'num_entries' return parameters is probably
599          * the "max entries" parameter - but in the TNG code they're all currently set to the same
600          * value (again I think this is wrong).
601          */
602
603         make_user_sam_entry_list(p->mem_ctx, &r_u->sam, &r_u->uni_acct_name, num_entries, pass);
604
605         init_samr_r_enum_dom_users(r_u, q_u->start_idx + num_entries, num_entries);
606
607         DEBUG(5,("_samr_enum_dom_users: %d\n", __LINE__));
608
609         return r_u->status;
610 }
611
612 /*******************************************************************
613 makes a SAM_ENTRY / UNISTR2* structure from a group list.
614 ********************************************************************/
615
616 static void make_group_sam_entry_list(TALLOC_CTX *ctx, SAM_ENTRY **sam_pp, UNISTR2 **uni_name_pp,
617                 uint32 num_sam_entries, DOMAIN_GRP *grp)
618 {
619         uint32 i;
620         SAM_ENTRY *sam;
621         UNISTR2 *uni_name;
622
623         *sam_pp = NULL;
624         *uni_name_pp = NULL;
625
626         if (num_sam_entries == 0)
627                 return;
628
629         sam = (SAM_ENTRY *)talloc_zero(ctx, sizeof(SAM_ENTRY)*num_sam_entries);
630
631         uni_name = (UNISTR2 *)talloc_zero(ctx, sizeof(UNISTR2)*num_sam_entries);
632
633         if (sam == NULL || uni_name == NULL) {
634                 DEBUG(0, ("NULL pointers in SAMR_R_QUERY_DISPINFO\n"));
635                 return;
636         }
637
638         for (i = 0; i < num_sam_entries; i++) {
639                 /*
640                  * JRA. I think this should include the null. TNG does not.
641                  */
642                 int len = strlen(grp[i].name)+1;
643
644                 init_sam_entry(&sam[i], len, grp[i].rid);
645                 init_unistr2(&uni_name[i], grp[i].name, len);
646         }
647
648         *sam_pp = sam;
649         *uni_name_pp = uni_name;
650 }
651
652 /*******************************************************************
653  Get the group entries - similar to get_sampwd_entries().
654  ********************************************************************/
655
656 static NTSTATUS get_group_alias_entries(TALLOC_CTX *ctx, DOMAIN_GRP **d_grp, DOM_SID *sid, uint32 start_idx,
657                                     uint32 *p_num_entries, uint32 max_entries)
658 {
659         fstring sid_str;
660         uint32 num_entries = 0;
661         int i;
662         GROUP_MAP smap;
663         GROUP_MAP *map;
664
665         sid_to_string(sid_str, sid);
666         DEBUG(5, ("get_group_alias_entries: enumerating aliases on SID: %s\n", sid_str));
667
668         *p_num_entries = 0;
669
670         /* well-known aliases */
671         if (sid_equal(sid, &global_sid_Builtin) && !lp_hide_local_users()) {
672                 
673                 enum_group_mapping(SID_NAME_ALIAS, &map, (int *)&num_entries, ENUM_ONLY_MAPPED, MAPPING_WITHOUT_PRIV);
674                 
675                 if (num_entries != 0) {         
676                         *d_grp=(DOMAIN_GRP *)talloc_zero(ctx, num_entries*sizeof(DOMAIN_GRP));
677                         if (*d_grp==NULL)
678                                 return NT_STATUS_NO_MEMORY;
679                         
680                         for(i=0; i<num_entries && i<max_entries; i++) {
681                                 fstrcpy((*d_grp)[i].name, map[i+start_idx].nt_name);
682                                 sid_split_rid(&map[i+start_idx].sid, &(*d_grp)[i].rid);
683                                 
684                         }
685                 }
686                 SAFE_FREE(map);
687                 
688         } else if (sid_equal(sid, get_global_sam_sid()) && !lp_hide_local_users()) {
689                 struct sys_grent *glist;
690                 struct sys_grent *grp;
691                 struct passwd *pw;
692                 gid_t winbind_gid_low, winbind_gid_high;
693                 BOOL winbind_groups_exist = lp_winbind_gid(&winbind_gid_low, &winbind_gid_high);
694
695                 /* local aliases */
696                 /* we return the UNIX groups here.  This seems to be the right */
697                 /* thing to do, since NT member servers return their local     */
698                 /* groups in the same situation.                               */
699
700                 /* use getgrent_list() to retrieve the list of groups to avoid
701                  * problems with getgrent possible infinite loop by internal
702                  * libc grent structures overwrites by called functions */
703                 grp = glist = getgrent_list();
704                 if (grp == NULL)
705                         return NT_STATUS_NO_MEMORY;
706                 
707                 for (; (num_entries < max_entries) && (grp != NULL); grp = grp->next) {
708                         uint32 trid;
709                         
710                         if(!get_group_from_gid(grp->gr_gid, &smap, MAPPING_WITHOUT_PRIV))
711                                 continue;
712                         
713                         if (smap.sid_name_use!=SID_NAME_ALIAS) {
714                                 continue;
715                         }
716
717                         sid_split_rid(&smap.sid, &trid);
718                         
719                         if (!sid_equal(sid, &smap.sid))
720                                 continue;
721
722                         /* Don't return winbind groups as they are not local! */
723                         if (winbind_groups_exist && (grp->gr_gid >= winbind_gid_low)&&(grp->gr_gid <= winbind_gid_high)) {
724                                 DEBUG(10,("get_group_alias_entries: not returing %s, not local.\n", smap.nt_name ));
725                                 continue;
726                         }
727
728                         /* Don't return user private groups... */
729
730                         if ((pw = Get_Pwnam(smap.nt_name)) != 0) {
731                                 DEBUG(10,("get_group_alias_entries: not returing %s, clashes with user.\n", smap.nt_name ));
732                                 continue;                       
733                         }
734
735                         for( i = 0; i < num_entries; i++)
736                                 if ( (*d_grp)[i].rid == trid )
737                                         break;
738
739                         if ( i < num_entries ) {
740                                 continue; /* rid was there, dup! */
741                         }
742
743                         /* JRA - added this for large group db enumeration... */
744
745                         if (start_idx > 0) {
746                                 /* skip the requested number of entries.
747                                         not very efficient, but hey...
748                                 */
749                                 start_idx--;
750                                 continue;
751                         }
752
753                         *d_grp=talloc_realloc(ctx,*d_grp, (num_entries+1)*sizeof(DOMAIN_GRP));
754                         if (*d_grp==NULL) {
755                                 grent_free(glist);
756                                 return NT_STATUS_NO_MEMORY;
757                         }
758
759                         fstrcpy((*d_grp)[num_entries].name, smap.nt_name);
760                         (*d_grp)[num_entries].rid = trid;
761                         num_entries++;
762                         DEBUG(10,("get_group_alias_entries: added entry %d, rid:%d\n", num_entries, trid));
763                 }
764
765                 grent_free(glist);
766         }
767
768         *p_num_entries = num_entries;
769
770         DEBUG(10,("get_group_alias_entries: returning %d entries\n", *p_num_entries));
771
772         if (num_entries >= max_entries)
773                 return STATUS_MORE_ENTRIES;
774         return NT_STATUS_OK;
775 }
776
777 /*******************************************************************
778  Get the group entries - similar to get_sampwd_entries().
779  ********************************************************************/
780
781 static NTSTATUS get_group_domain_entries(TALLOC_CTX *ctx, DOMAIN_GRP **d_grp, DOM_SID *sid, uint32 start_idx,
782                                      uint32 *p_num_entries, uint32 max_entries)
783 {
784         GROUP_MAP *map=NULL;
785         int i;
786         uint32 group_entries = 0;
787         uint32 num_entries = 0;
788
789         *p_num_entries = 0;
790
791         enum_group_mapping(SID_NAME_DOM_GRP, &map, (int *)&group_entries, ENUM_ONLY_MAPPED, MAPPING_WITHOUT_PRIV);
792
793         num_entries=group_entries-start_idx;
794
795         /* limit the number of entries */
796         if (num_entries>max_entries) {
797                 DEBUG(5,("Limiting to %d entries\n", max_entries));
798                 num_entries=max_entries;
799         }
800
801         *d_grp=(DOMAIN_GRP *)talloc_zero(ctx, num_entries*sizeof(DOMAIN_GRP));
802         if (num_entries!=0 && *d_grp==NULL){
803                 SAFE_FREE(map);
804                 return NT_STATUS_NO_MEMORY;
805         }
806         
807         for (i=0; i<num_entries; i++) {
808                 fstrcpy((*d_grp)[i].name, map[i+start_idx].nt_name);
809                 fstrcpy((*d_grp)[i].comment, map[i+start_idx].comment);
810                 sid_split_rid(&map[i+start_idx].sid, &(*d_grp)[i].rid);
811                 (*d_grp)[i].attr=SID_NAME_DOM_GRP;
812         }
813
814         SAFE_FREE(map);
815
816         *p_num_entries = num_entries;
817
818         return NT_STATUS_OK;
819 }
820
821 /*******************************************************************
822  samr_reply_enum_dom_groups
823  Only reply with one group - domain admins. This must be fixed for
824  a real PDC. JRA.
825  ********************************************************************/
826
827 NTSTATUS _samr_enum_dom_groups(pipes_struct *p, SAMR_Q_ENUM_DOM_GROUPS *q_u, SAMR_R_ENUM_DOM_GROUPS *r_u)
828 {
829         DOMAIN_GRP *grp=NULL;
830         uint32 num_entries;
831         DOM_SID sid;
832
833         r_u->status = NT_STATUS_OK;
834
835         if (!get_lsa_policy_samr_sid(p, &q_u->pol, &sid))
836                 return NT_STATUS_INVALID_HANDLE;
837
838         DEBUG(5,("samr_reply_enum_dom_groups: %d\n", __LINE__));
839
840         /* the domain group array is being allocated in the function below */
841         get_group_domain_entries(p->mem_ctx, &grp, &sid, q_u->start_idx, &num_entries, MAX_SAM_ENTRIES);
842
843         make_group_sam_entry_list(p->mem_ctx, &r_u->sam, &r_u->uni_grp_name, num_entries, grp);
844
845         init_samr_r_enum_dom_groups(r_u, q_u->start_idx, num_entries);
846
847         DEBUG(5,("samr_enum_dom_groups: %d\n", __LINE__));
848
849         return r_u->status;
850 }
851
852
853 /*******************************************************************
854  samr_reply_enum_dom_aliases
855  ********************************************************************/
856
857 NTSTATUS _samr_enum_dom_aliases(pipes_struct *p, SAMR_Q_ENUM_DOM_ALIASES *q_u, SAMR_R_ENUM_DOM_ALIASES *r_u)
858 {
859         DOMAIN_GRP *grp=NULL;
860         uint32 num_entries = 0;
861         fstring sid_str;
862         DOM_SID sid;
863         NTSTATUS status;
864         
865         r_u->status = NT_STATUS_OK;
866
867         if (!get_lsa_policy_samr_sid(p, &q_u->pol, &sid))
868                 return NT_STATUS_INVALID_HANDLE;
869
870         sid_to_string(sid_str, &sid);
871         DEBUG(5,("samr_reply_enum_dom_aliases: sid %s\n", sid_str));
872
873         status = get_group_alias_entries(p->mem_ctx, &grp, &sid, q_u->start_idx, 
874                                          &num_entries, MAX_SAM_ENTRIES);
875         if (NT_STATUS_IS_ERR(status)) return status;
876
877         make_group_sam_entry_list(p->mem_ctx, &r_u->sam, &r_u->uni_grp_name, num_entries, grp);
878
879         /*safe_free(grp);*/
880
881         init_samr_r_enum_dom_aliases(r_u, q_u->start_idx + num_entries, num_entries);
882
883         DEBUG(5,("samr_enum_dom_aliases: %d\n", __LINE__));
884
885         return r_u->status;
886 }
887
888 /*******************************************************************
889  samr_reply_query_dispinfo
890  ********************************************************************/
891 NTSTATUS _samr_query_dispinfo(pipes_struct *p, SAMR_Q_QUERY_DISPINFO *q_u, SAMR_R_QUERY_DISPINFO *r_u)
892 {
893         struct samr_info *info = NULL;
894         uint32 struct_size=0x20; /* W2K always reply that, client doesn't care */
895         uint16 acb_mask;
896         
897         uint32 max_entries=q_u->max_entries;
898         uint32 enum_context=q_u->start_idx;
899         uint32 max_size=q_u->max_size;
900
901         SAM_DISPINFO_CTR *ctr;
902         uint32 temp_size=0, total_data_size=0;
903         NTSTATUS disp_ret;
904         uint32 num_account = 0;
905         enum remote_arch_types ra_type = get_remote_arch();
906         int max_sam_entries;
907
908         max_sam_entries = (ra_type == RA_WIN95) ? MAX_SAM_ENTRIES_W95 : MAX_SAM_ENTRIES_W2K;
909
910         DEBUG(5, ("samr_reply_query_dispinfo: %d\n", __LINE__));
911         r_u->status = NT_STATUS_OK;
912
913         /* find the policy handle.  open a policy on it. */
914         if (!find_policy_by_hnd(p, &q_u->domain_pol, (void **)&info))
915                 return NT_STATUS_INVALID_HANDLE;
916
917         /*
918          * calculate how many entries we will return.
919          * based on 
920          * - the number of entries the client asked
921          * - our limit on that
922          * - the starting point (enumeration context)
923          * - the buffer size the client will accept
924          */
925
926         /*
927          * We are a lot more like W2K. Instead of reading the SAM
928          * each time to find the records we need to send back,
929          * we read it once and link that copy to the sam handle.
930          * For large user list (over the MAX_SAM_ENTRIES)
931          * it's a definitive win.
932          * second point to notice: between enumerations
933          * our sam is now the same as it's a snapshoot.
934          * third point: got rid of the static SAM_USER_21 struct
935          * no more intermediate.
936          * con: it uses much more memory, as a full copy is stored
937          * in memory.
938          *
939          * If you want to change it, think twice and think
940          * of the second point , that's really important.
941          *
942          * JFM, 12/20/2001
943          */
944
945         /* Get what we need from the password database */
946
947         if (q_u->switch_level==2)
948                 acb_mask = ACB_WSTRUST;
949         else
950                 acb_mask = ACB_NORMAL;
951
952         /* Get what we need from the password database */
953         switch (q_u->switch_level) {
954                 case 0x1:
955                 case 0x2:
956                 case 0x4:
957                         become_root();          
958                         r_u->status=load_sampwd_entries(info, acb_mask);
959                         unbecome_root();
960                         if (!NT_STATUS_IS_OK(r_u->status)) {
961                                 DEBUG(5, ("_samr_query_dispinfo: load_sampwd_entries failed\n"));
962                                 return r_u->status;
963                         }
964                         num_account = info->disp_info.num_user_account;
965                         break;
966                 case 0x3:
967                 case 0x5:
968                         r_u->status = load_group_domain_entries(info, &info->sid);
969                         if (!NT_STATUS_IS_OK(r_u->status))
970                                 return r_u->status;
971                         num_account = info->disp_info.num_group_account;
972                         break;
973                 default:
974                         DEBUG(0,("_samr_query_dispinfo: Unknown info level (%u)\n", (unsigned int)q_u->switch_level ));
975                         return NT_STATUS_INVALID_INFO_CLASS;
976         }
977
978         /* first limit the number of entries we will return */
979         if(max_entries > max_sam_entries) {
980                 DEBUG(5, ("samr_reply_query_dispinfo: client requested %d entries, limiting to %d\n", max_entries, max_sam_entries));
981                 max_entries = max_sam_entries;
982         }
983
984         if (enum_context > num_account) {
985                 DEBUG(5, ("samr_reply_query_dispinfo: enumeration handle over total entries\n"));
986                 return NT_STATUS_OK;
987         }
988
989         /* verify we won't overflow */
990         if (max_entries > num_account-enum_context) {
991                 max_entries = num_account-enum_context;
992                 DEBUG(5, ("samr_reply_query_dispinfo: only %d entries to return\n", max_entries));
993         }
994
995         /* calculate the size and limit on the number of entries we will return */
996         temp_size=max_entries*struct_size;
997         
998         if (temp_size>max_size) {
999                 max_entries=MIN((max_size/struct_size),max_entries);;
1000                 DEBUG(5, ("samr_reply_query_dispinfo: buffer size limits to only %d entries\n", max_entries));
1001         }
1002
1003         if (!(ctr = (SAM_DISPINFO_CTR *)talloc_zero(p->mem_ctx,sizeof(SAM_DISPINFO_CTR))))
1004                 return NT_STATUS_NO_MEMORY;
1005
1006         ZERO_STRUCTP(ctr);
1007
1008         /* Now create reply structure */
1009         switch (q_u->switch_level) {
1010         case 0x1:
1011                 if (max_entries) {
1012                         if (!(ctr->sam.info1 = (SAM_DISPINFO_1 *)talloc_zero(p->mem_ctx,max_entries*sizeof(SAM_DISPINFO_1))))
1013                                 return NT_STATUS_NO_MEMORY;
1014                 }
1015                 disp_ret = init_sam_dispinfo_1(p->mem_ctx, ctr->sam.info1, max_entries, enum_context, info->disp_info.disp_user_info);
1016                 if (!NT_STATUS_IS_OK(disp_ret))
1017                         return disp_ret;
1018                 break;
1019         case 0x2:
1020                 if (max_entries) {
1021                         if (!(ctr->sam.info2 = (SAM_DISPINFO_2 *)talloc_zero(p->mem_ctx,max_entries*sizeof(SAM_DISPINFO_2))))
1022                                 return NT_STATUS_NO_MEMORY;
1023                 }
1024                 disp_ret = init_sam_dispinfo_2(p->mem_ctx, ctr->sam.info2, max_entries, enum_context, info->disp_info.disp_user_info);
1025                 if (!NT_STATUS_IS_OK(disp_ret))
1026                         return disp_ret;
1027                 break;
1028         case 0x3:
1029                 if (max_entries) {
1030                         if (!(ctr->sam.info3 = (SAM_DISPINFO_3 *)talloc_zero(p->mem_ctx,max_entries*sizeof(SAM_DISPINFO_3))))
1031                                 return NT_STATUS_NO_MEMORY;
1032                 }
1033                 disp_ret = init_sam_dispinfo_3(p->mem_ctx, ctr->sam.info3, max_entries, enum_context, info->disp_info.disp_group_info);
1034                 if (!NT_STATUS_IS_OK(disp_ret))
1035                         return disp_ret;
1036                 break;
1037         case 0x4:
1038                 if (max_entries) {
1039                         if (!(ctr->sam.info4 = (SAM_DISPINFO_4 *)talloc_zero(p->mem_ctx,max_entries*sizeof(SAM_DISPINFO_4))))
1040                                 return NT_STATUS_NO_MEMORY;
1041                 }
1042                 disp_ret = init_sam_dispinfo_4(p->mem_ctx, ctr->sam.info4, max_entries, enum_context, info->disp_info.disp_user_info);
1043                 if (!NT_STATUS_IS_OK(disp_ret))
1044                         return disp_ret;
1045                 break;
1046         case 0x5:
1047                 if (max_entries) {
1048                         if (!(ctr->sam.info5 = (SAM_DISPINFO_5 *)talloc_zero(p->mem_ctx,max_entries*sizeof(SAM_DISPINFO_5))))
1049                                 return NT_STATUS_NO_MEMORY;
1050                 }
1051                 disp_ret = init_sam_dispinfo_5(p->mem_ctx, ctr->sam.info5, max_entries, enum_context, info->disp_info.disp_group_info);
1052                 if (!NT_STATUS_IS_OK(disp_ret))
1053                         return disp_ret;
1054                 break;
1055
1056         default:
1057                 ctr->sam.info = NULL;
1058                 return NT_STATUS_INVALID_INFO_CLASS;
1059         }
1060
1061         /* calculate the total size */
1062         total_data_size=num_account*struct_size;
1063
1064         if (enum_context+max_entries < num_account)
1065                 r_u->status = STATUS_MORE_ENTRIES;
1066
1067         DEBUG(5, ("_samr_query_dispinfo: %d\n", __LINE__));
1068
1069         init_samr_r_query_dispinfo(r_u, max_entries, total_data_size, temp_size, q_u->switch_level, ctr, r_u->status);
1070
1071         return r_u->status;
1072
1073 }
1074
1075 /*******************************************************************
1076  samr_reply_query_aliasinfo
1077  ********************************************************************/
1078
1079 NTSTATUS _samr_query_aliasinfo(pipes_struct *p, SAMR_Q_QUERY_ALIASINFO *q_u, SAMR_R_QUERY_ALIASINFO *r_u)
1080 {
1081         struct samr_info *info = NULL;
1082         GROUP_MAP map;
1083
1084         r_u->status = NT_STATUS_OK;
1085
1086         DEBUG(5,("_samr_query_aliasinfo: %d\n", __LINE__));
1087
1088         /* find the policy handle.  open a policy on it. */
1089         if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info))
1090                 return NT_STATUS_INVALID_HANDLE;
1091
1092         if (!sid_check_is_in_our_domain(&info->sid) &&
1093             !sid_check_is_in_builtin(&info->sid))
1094                 return NT_STATUS_OBJECT_TYPE_MISMATCH;
1095
1096         if(!get_local_group_from_sid(info->sid, &map, MAPPING_WITHOUT_PRIV))
1097                 return NT_STATUS_NO_SUCH_ALIAS;
1098
1099         switch (q_u->switch_level) {
1100         case 1:
1101                 r_u->ptr = 1;
1102                 r_u->ctr.switch_value1 = 1;
1103                 init_samr_alias_info1(&r_u->ctr.alias.info1, map.nt_name, 1, map.comment);
1104                 break;
1105         case 3:
1106                 r_u->ptr = 1;
1107                 r_u->ctr.switch_value1 = 3;
1108                 init_samr_alias_info3(&r_u->ctr.alias.info3, map.comment);
1109                 break;
1110         default:
1111                 return NT_STATUS_INVALID_INFO_CLASS;
1112         }
1113
1114         DEBUG(5,("_samr_query_aliasinfo: %d\n", __LINE__));
1115
1116         return r_u->status;
1117 }
1118
1119 #if 0
1120 /*******************************************************************
1121  samr_reply_lookup_ids
1122  ********************************************************************/
1123
1124  uint32 _samr_lookup_ids(pipes_struct *p, SAMR_Q_LOOKUP_IDS *q_u, SAMR_R_LOOKUP_IDS *r_u)
1125 {
1126     uint32 rid[MAX_SAM_ENTRIES];
1127     int num_rids = q_u->num_sids1;
1128
1129     r_u->status = NT_STATUS_OK;
1130
1131     DEBUG(5,("_samr_lookup_ids: %d\n", __LINE__));
1132
1133     if (num_rids > MAX_SAM_ENTRIES) {
1134         num_rids = MAX_SAM_ENTRIES;
1135         DEBUG(5,("_samr_lookup_ids: truncating entries to %d\n", num_rids));
1136     }
1137
1138 #if 0
1139     int i;
1140     SMB_ASSERT_ARRAY(q_u->uni_user_name, num_rids);
1141
1142     for (i = 0; i < num_rids && status == 0; i++)
1143     {
1144         struct sam_passwd *sam_pass;
1145         fstring user_name;
1146
1147
1148         fstrcpy(user_name, unistrn2(q_u->uni_user_name[i].buffer,
1149                                     q_u->uni_user_name[i].uni_str_len));
1150
1151         /* find the user account */
1152         become_root();
1153         sam_pass = get_smb21pwd_entry(user_name, 0);
1154         unbecome_root();
1155
1156         if (sam_pass == NULL)
1157         {
1158             status = 0xC0000000 | NT_STATUS_NO_SUCH_USER;
1159             rid[i] = 0;
1160         }
1161         else
1162         {
1163             rid[i] = sam_pass->user_rid;
1164         }
1165     }
1166 #endif
1167
1168     num_rids = 1;
1169     rid[0] = BUILTIN_ALIAS_RID_USERS;
1170
1171     init_samr_r_lookup_ids(&r_u, num_rids, rid, NT_STATUS_OK);
1172
1173     DEBUG(5,("_samr_lookup_ids: %d\n", __LINE__));
1174
1175     return r_u->status;
1176 }
1177 #endif
1178
1179 /*******************************************************************
1180  _samr_lookup_names
1181  ********************************************************************/
1182
1183 NTSTATUS _samr_lookup_names(pipes_struct *p, SAMR_Q_LOOKUP_NAMES *q_u, SAMR_R_LOOKUP_NAMES *r_u)
1184 {
1185         uint32 rid[MAX_SAM_ENTRIES];
1186         uint32 local_rid;
1187         enum SID_NAME_USE type[MAX_SAM_ENTRIES];
1188         enum SID_NAME_USE local_type;
1189         int i;
1190         int num_rids = q_u->num_names2;
1191         DOM_SID pol_sid;
1192         fstring sid_str;
1193
1194         r_u->status = NT_STATUS_OK;
1195
1196         DEBUG(5,("_samr_lookup_names: %d\n", __LINE__));
1197
1198         ZERO_ARRAY(rid);
1199         ZERO_ARRAY(type);
1200
1201         if (!get_lsa_policy_samr_sid(p, &q_u->pol, &pol_sid)) {
1202                 init_samr_r_lookup_names(p->mem_ctx, r_u, 0, NULL, NULL, NT_STATUS_OBJECT_TYPE_MISMATCH);
1203                 return r_u->status;
1204         }
1205
1206         if (num_rids > MAX_SAM_ENTRIES) {
1207                 num_rids = MAX_SAM_ENTRIES;
1208                 DEBUG(5,("_samr_lookup_names: truncating entries to %d\n", num_rids));
1209         }
1210
1211         DEBUG(5,("_samr_lookup_names: looking name on SID %s\n", sid_to_string(sid_str, &pol_sid)));
1212         
1213         become_root(); /* local_lookup_name can require root privs */
1214
1215         for (i = 0; i < num_rids; i++) {
1216                 fstring name;
1217                 DOM_SID sid;
1218
1219                 r_u->status = NT_STATUS_NONE_MAPPED;
1220
1221                 rid [i] = 0xffffffff;
1222                 type[i] = SID_NAME_UNKNOWN;
1223
1224                 rpcstr_pull(name, q_u->uni_name[i].buffer, sizeof(name), q_u->uni_name[i].uni_str_len*2, 0);
1225
1226                 /*
1227                  * we are only looking for a name
1228                  * the SID we get back can be outside
1229                  * the scope of the pol_sid
1230                  * 
1231                  * in clear: it prevents to reply to domain\group: yes
1232                  * when only builtin\group exists.
1233                  *
1234                  * a cleaner code is to add the sid of the domain we're looking in
1235                  * to the local_lookup_name function.
1236                  */
1237                 if(local_lookup_name(name, &sid, &local_type)) {
1238                         sid_split_rid(&sid, &local_rid);
1239                                 
1240                         if (sid_equal(&sid, &pol_sid)) {
1241                                 rid[i]=local_rid;
1242                                 type[i]=local_type;
1243                                 r_u->status = NT_STATUS_OK;
1244                         }
1245                 }
1246         }
1247
1248         unbecome_root();
1249
1250         init_samr_r_lookup_names(p->mem_ctx, r_u, num_rids, rid, (uint32 *)type, r_u->status);
1251
1252         DEBUG(5,("_samr_lookup_names: %d\n", __LINE__));
1253
1254         return r_u->status;
1255 }
1256
1257 /*******************************************************************
1258  _samr_chgpasswd_user
1259  ********************************************************************/
1260
1261 NTSTATUS _samr_chgpasswd_user(pipes_struct *p, SAMR_Q_CHGPASSWD_USER *q_u, SAMR_R_CHGPASSWD_USER *r_u)
1262 {
1263     fstring user_name;
1264     fstring wks;
1265
1266     DEBUG(5,("_samr_chgpasswd_user: %d\n", __LINE__));
1267
1268     r_u->status = NT_STATUS_OK;
1269
1270     rpcstr_pull(user_name, q_u->uni_user_name.buffer, sizeof(user_name), q_u->uni_user_name.uni_str_len*2, 0);
1271     rpcstr_pull(wks, q_u->uni_dest_host.buffer, sizeof(wks), q_u->uni_dest_host.uni_str_len*2,0);
1272
1273     DEBUG(5,("samr_chgpasswd_user: user: %s wks: %s\n", user_name, wks));
1274
1275         /*
1276          * Pass the user through the NT -> unix user mapping
1277          * function.
1278          */
1279  
1280         (void)map_username(user_name);
1281  
1282         /*
1283          * UNIX username case mangling not required, pass_oem_change 
1284          * is case insensitive.
1285          */
1286
1287     if (!pass_oem_change(user_name, q_u->lm_newpass.pass, q_u->lm_oldhash.hash,
1288                          q_u->nt_newpass.pass, q_u->nt_oldhash.hash))
1289         r_u->status = NT_STATUS_WRONG_PASSWORD;
1290
1291     init_samr_r_chgpasswd_user(r_u, r_u->status);
1292
1293     DEBUG(5,("_samr_chgpasswd_user: %d\n", __LINE__));
1294
1295     return r_u->status;
1296 }
1297
1298 /*******************************************************************
1299 makes a SAMR_R_LOOKUP_RIDS structure.
1300 ********************************************************************/
1301
1302 static BOOL make_samr_lookup_rids(TALLOC_CTX *ctx, uint32 num_names, fstring names[],
1303             UNIHDR **pp_hdr_name, UNISTR2 **pp_uni_name)
1304 {
1305         uint32 i;
1306         UNIHDR *hdr_name=NULL;
1307         UNISTR2 *uni_name=NULL;
1308
1309         *pp_uni_name = NULL;
1310         *pp_hdr_name = NULL;
1311
1312         if (num_names != 0) {
1313                 hdr_name = (UNIHDR *)talloc_zero(ctx, sizeof(UNIHDR)*num_names);
1314                 if (hdr_name == NULL)
1315                         return False;
1316
1317                 uni_name = (UNISTR2 *)talloc_zero(ctx,sizeof(UNISTR2)*num_names);
1318                 if (uni_name == NULL)
1319                         return False;
1320         }
1321
1322         for (i = 0; i < num_names; i++) {
1323                 int len = names[i] != NULL ? strlen(names[i]) : 0;
1324                 DEBUG(10, ("names[%d]:%s\n", i, names[i]));
1325                 init_uni_hdr(&hdr_name[i], len);
1326                 init_unistr2(&uni_name[i], names[i], len);
1327         }
1328
1329         *pp_uni_name = uni_name;
1330         *pp_hdr_name = hdr_name;
1331
1332         return True;
1333 }
1334
1335 /*******************************************************************
1336  _samr_lookup_rids
1337  ********************************************************************/
1338
1339 NTSTATUS _samr_lookup_rids(pipes_struct *p, SAMR_Q_LOOKUP_RIDS *q_u, SAMR_R_LOOKUP_RIDS *r_u)
1340 {
1341         fstring group_names[MAX_SAM_ENTRIES];
1342         uint32 *group_attrs = NULL;
1343         UNIHDR *hdr_name = NULL;
1344         UNISTR2 *uni_name = NULL;
1345         DOM_SID pol_sid;
1346         int num_rids = q_u->num_rids1;
1347         int i;
1348
1349         r_u->status = NT_STATUS_OK;
1350
1351         DEBUG(5,("_samr_lookup_rids: %d\n", __LINE__));
1352
1353         /* find the policy handle.  open a policy on it. */
1354         if (!get_lsa_policy_samr_sid(p, &q_u->pol, &pol_sid))
1355                 return NT_STATUS_INVALID_HANDLE;
1356
1357         if (num_rids > MAX_SAM_ENTRIES) {
1358                 num_rids = MAX_SAM_ENTRIES;
1359                 DEBUG(5,("_samr_lookup_rids: truncating entries to %d\n", num_rids));
1360         }
1361
1362         if (num_rids) {
1363                 if ((group_attrs = (uint32 *)talloc_zero(p->mem_ctx, num_rids * sizeof(uint32))) == NULL)
1364                         return NT_STATUS_NO_MEMORY;
1365         }
1366  
1367         r_u->status = NT_STATUS_NONE_MAPPED;
1368
1369         become_root();  /* lookup_sid can require root privs */
1370
1371         for (i = 0; i < num_rids; i++) {
1372                 fstring tmpname;
1373                 fstring domname;
1374                 DOM_SID sid;
1375                 enum SID_NAME_USE type;
1376
1377                 group_attrs[i] = SID_NAME_UNKNOWN;
1378                 *group_names[i] = '\0';
1379
1380                 if (sid_equal(&pol_sid, get_global_sam_sid())) {
1381                         sid_copy(&sid, &pol_sid);
1382                         sid_append_rid(&sid, q_u->rid[i]);
1383
1384                         if (lookup_sid(&sid, domname, tmpname, &type)) {
1385                                 r_u->status = NT_STATUS_OK;
1386                                 group_attrs[i] = (uint32)type;
1387                                 fstrcpy(group_names[i],tmpname);
1388                                 DEBUG(5,("_samr_lookup_rids: %s:%d\n", group_names[i], group_attrs[i]));
1389                         }
1390                 }
1391         }
1392
1393         unbecome_root();
1394
1395         if(!make_samr_lookup_rids(p->mem_ctx, num_rids, group_names, &hdr_name, &uni_name))
1396                 return NT_STATUS_NO_MEMORY;
1397
1398         init_samr_r_lookup_rids(r_u, num_rids, hdr_name, uni_name, group_attrs);
1399
1400         DEBUG(5,("_samr_lookup_rids: %d\n", __LINE__));
1401
1402         return r_u->status;
1403 }
1404
1405 /*******************************************************************
1406  _api_samr_open_user. Safe - gives out no passwd info.
1407  ********************************************************************/
1408
1409 NTSTATUS _api_samr_open_user(pipes_struct *p, SAMR_Q_OPEN_USER *q_u, SAMR_R_OPEN_USER *r_u)
1410 {
1411         SAM_ACCOUNT *sampass=NULL;
1412         DOM_SID sid;
1413         POLICY_HND domain_pol = q_u->domain_pol;
1414         POLICY_HND *user_pol = &r_u->user_pol;
1415         struct samr_info *info = NULL;
1416         BOOL ret;
1417         NTSTATUS nt_status;
1418
1419         r_u->status = NT_STATUS_OK;
1420
1421         /* find the domain policy handle. */
1422         if (!find_policy_by_hnd(p, &domain_pol, NULL))
1423                 return NT_STATUS_INVALID_HANDLE;
1424
1425         nt_status = pdb_init_sam_talloc(p->mem_ctx, &sampass);
1426         if (!NT_STATUS_IS_OK(nt_status)) {
1427                 return nt_status;
1428         }
1429
1430         /* Get the domain SID stored in the domain policy */
1431         if(!get_lsa_policy_samr_sid(p, &domain_pol, &sid))
1432                 return NT_STATUS_INVALID_HANDLE;
1433
1434         /* append the user's RID to it */
1435         if(!sid_append_rid(&sid, q_u->user_rid))
1436                 return NT_STATUS_NO_SUCH_USER;
1437
1438         become_root();
1439         ret=pdb_getsampwsid(sampass, &sid);
1440         unbecome_root();
1441
1442         /* check that the SID exists in our domain. */
1443         if (ret == False) {
1444                 return NT_STATUS_NO_SUCH_USER;
1445         }
1446
1447         pdb_free_sam(&sampass);
1448
1449         /* associate the user's SID with the new handle. */
1450         if ((info = get_samr_info_by_sid(&sid)) == NULL)
1451                 return NT_STATUS_NO_MEMORY;
1452
1453         /* get a (unique) handle.  open a policy on it. */
1454         if (!create_policy_hnd(p, user_pol, free_samr_info, (void *)info))
1455                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1456
1457         return r_u->status;
1458 }
1459
1460 /*************************************************************************
1461  get_user_info_10. Safe. Only gives out acb bits.
1462  *************************************************************************/
1463
1464 static NTSTATUS get_user_info_10(TALLOC_CTX *mem_ctx, SAM_USER_INFO_10 *id10, DOM_SID *user_sid)
1465 {
1466         SAM_ACCOUNT *smbpass=NULL;
1467         BOOL ret;
1468         NTSTATUS nt_status;
1469
1470         nt_status = pdb_init_sam_talloc(mem_ctx, &smbpass);
1471         
1472         if (!NT_STATUS_IS_OK(nt_status)) {
1473                 return nt_status;
1474         }
1475
1476         become_root();
1477         ret = pdb_getsampwsid(smbpass, user_sid);
1478         unbecome_root();
1479
1480         if (ret==False) {
1481                 DEBUG(4,("User %s not found\n", sid_string_static(user_sid)));
1482                 return NT_STATUS_NO_SUCH_USER;
1483         }
1484
1485         DEBUG(3,("User:[%s]\n", pdb_get_username(smbpass) ));
1486
1487         ZERO_STRUCTP(id10);
1488         init_sam_user_info10(id10, pdb_get_acct_ctrl(smbpass) );
1489
1490         pdb_free_sam(&smbpass);
1491
1492         return NT_STATUS_OK;
1493 }
1494
1495 /*************************************************************************
1496  get_user_info_12. OK - this is the killer as it gives out password info.
1497  Ensure that this is only allowed on an encrypted connection with a root
1498  user. JRA. 
1499  *************************************************************************/
1500
1501 static NTSTATUS get_user_info_12(pipes_struct *p, TALLOC_CTX *mem_ctx, SAM_USER_INFO_12 * id12, DOM_SID *user_sid)
1502 {
1503         SAM_ACCOUNT *smbpass=NULL;
1504         BOOL ret;
1505         NTSTATUS nt_status;
1506
1507         if (!p->ntlmssp_auth_validated)
1508                 return NT_STATUS_ACCESS_DENIED;
1509
1510         if (!(p->ntlmssp_chal_flags & NTLMSSP_NEGOTIATE_SIGN) || !(p->ntlmssp_chal_flags & NTLMSSP_NEGOTIATE_SEAL))
1511                 return NT_STATUS_ACCESS_DENIED;
1512
1513         /*
1514          * Do *NOT* do become_root()/unbecome_root() here ! JRA.
1515          */
1516
1517         nt_status = pdb_init_sam_talloc(mem_ctx, &smbpass);
1518         
1519         if (!NT_STATUS_IS_OK(nt_status)) {
1520                 return nt_status;
1521         }
1522
1523         ret = pdb_getsampwsid(smbpass, user_sid);
1524
1525         if (ret == False) {
1526                 DEBUG(4, ("User %s not found\n", sid_string_static(user_sid)));
1527                 pdb_free_sam(&smbpass);
1528                 return (geteuid() == (uid_t)0) ? NT_STATUS_NO_SUCH_USER : NT_STATUS_ACCESS_DENIED;
1529         }
1530
1531         DEBUG(3,("User:[%s] 0x%x\n", pdb_get_username(smbpass), pdb_get_acct_ctrl(smbpass) ));
1532
1533         if ( pdb_get_acct_ctrl(smbpass) & ACB_DISABLED) {
1534                 pdb_free_sam(&smbpass);
1535                 return NT_STATUS_ACCOUNT_DISABLED;
1536         }
1537
1538         ZERO_STRUCTP(id12);
1539         init_sam_user_info12(id12, pdb_get_lanman_passwd(smbpass), pdb_get_nt_passwd(smbpass));
1540         
1541         pdb_free_sam(&smbpass);
1542
1543         return NT_STATUS_OK;
1544 }
1545
1546 /*************************************************************************
1547  get_user_info_20
1548  *************************************************************************/
1549
1550 static NTSTATUS get_user_info_20(TALLOC_CTX *mem_ctx, SAM_USER_INFO_20 *id20, DOM_SID *user_sid)
1551 {
1552         SAM_ACCOUNT *sampass=NULL;
1553         BOOL ret;
1554
1555         pdb_init_sam_talloc(mem_ctx, &sampass);
1556
1557         become_root();
1558         ret = pdb_getsampwsid(sampass, user_sid);
1559         unbecome_root();
1560
1561         if (ret == False) {
1562                 DEBUG(4,("User %s not found\n", sid_string_static(user_sid)));
1563                 return NT_STATUS_NO_SUCH_USER;
1564         }
1565
1566         samr_clear_sam_passwd(sampass);
1567
1568         DEBUG(3,("User:[%s]\n",  pdb_get_username(sampass) ));
1569
1570         ZERO_STRUCTP(id20);
1571         init_sam_user_info20A(id20, sampass);
1572         
1573         pdb_free_sam(&sampass);
1574
1575         return NT_STATUS_OK;
1576 }
1577
1578 /*************************************************************************
1579  get_user_info_21
1580  *************************************************************************/
1581
1582 static NTSTATUS get_user_info_21(TALLOC_CTX *mem_ctx, SAM_USER_INFO_21 *id21, DOM_SID *user_sid)
1583 {
1584         SAM_ACCOUNT *sampass=NULL;
1585         BOOL ret;
1586         NTSTATUS nt_status;
1587
1588         nt_status = pdb_init_sam_talloc(mem_ctx, &sampass);
1589         if (!NT_STATUS_IS_OK(nt_status)) {
1590                 return nt_status;
1591         }
1592
1593         become_root();
1594         ret = pdb_getsampwsid(sampass, user_sid);
1595         unbecome_root();
1596
1597         if (ret == False) {
1598                 DEBUG(4,("User %s not found\n", sid_string_static(user_sid)));
1599                 return NT_STATUS_NO_SUCH_USER;
1600         }
1601
1602         samr_clear_sam_passwd(sampass);
1603
1604         DEBUG(3,("User:[%s]\n",  pdb_get_username(sampass) ));
1605
1606         ZERO_STRUCTP(id21);
1607         init_sam_user_info21A(id21, sampass);
1608         
1609         pdb_free_sam(&sampass);
1610
1611         return NT_STATUS_OK;
1612 }
1613
1614 /*******************************************************************
1615  _samr_query_userinfo
1616  ********************************************************************/
1617
1618 NTSTATUS _samr_query_userinfo(pipes_struct *p, SAMR_Q_QUERY_USERINFO *q_u, SAMR_R_QUERY_USERINFO *r_u)
1619 {
1620         SAM_USERINFO_CTR *ctr;
1621         struct samr_info *info = NULL;
1622
1623         r_u->status=NT_STATUS_OK;
1624
1625         /* search for the handle */
1626         if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info))
1627                 return NT_STATUS_INVALID_HANDLE;
1628
1629         if (!sid_check_is_in_our_domain(&info->sid))
1630                 return NT_STATUS_OBJECT_TYPE_MISMATCH;
1631
1632         DEBUG(5,("_samr_query_userinfo: sid:%s\n", sid_string_static(&info->sid)));
1633
1634         ctr = (SAM_USERINFO_CTR *)talloc_zero(p->mem_ctx, sizeof(SAM_USERINFO_CTR));
1635         if (!ctr)
1636                 return NT_STATUS_NO_MEMORY;
1637
1638         ZERO_STRUCTP(ctr);
1639
1640         /* ok!  user info levels (lots: see MSDEV help), off we go... */
1641         ctr->switch_value = q_u->switch_value;
1642
1643         switch (q_u->switch_value) {
1644         case 0x10:
1645                 ctr->info.id10 = (SAM_USER_INFO_10 *)talloc_zero(p->mem_ctx, sizeof(SAM_USER_INFO_10));
1646                 if (ctr->info.id10 == NULL)
1647                         return NT_STATUS_NO_MEMORY;
1648
1649                 if (!NT_STATUS_IS_OK(r_u->status = get_user_info_10(p->mem_ctx, ctr->info.id10, &info->sid)))
1650                         return r_u->status;
1651                 break;
1652
1653 #if 0
1654 /* whoops - got this wrong.  i think.  or don't understand what's happening. */
1655         case 0x11:
1656         {
1657             NTTIME expire;
1658             info = (void *)&id11;
1659
1660             expire.low = 0xffffffff;
1661             expire.high = 0x7fffffff;
1662
1663             ctr->info.id = (SAM_USER_INFO_11 *)talloc_zero(p->mem_ctx,
1664                                     sizeof
1665                                     (*ctr->
1666                                      info.
1667                                      id11));
1668             ZERO_STRUCTP(ctr->info.id11);
1669             init_sam_user_info11(ctr->info.id11, &expire,
1670                          "BROOKFIELDS$",    /* name */
1671                          0x03ef,    /* user rid */
1672                          0x201, /* group rid */
1673                          0x0080);   /* acb info */
1674
1675             break;
1676         }
1677 #endif
1678
1679         case 0x12:
1680                 ctr->info.id12 = (SAM_USER_INFO_12 *)talloc_zero(p->mem_ctx, sizeof(SAM_USER_INFO_12));
1681                 if (ctr->info.id12 == NULL)
1682                         return NT_STATUS_NO_MEMORY;
1683
1684                 if (!NT_STATUS_IS_OK(r_u->status = get_user_info_12(p, p->mem_ctx, ctr->info.id12, &info->sid)))
1685                         return r_u->status;
1686                 break;
1687                 
1688         case 20:
1689                 ctr->info.id20 = (SAM_USER_INFO_20 *)talloc_zero(p->mem_ctx,sizeof(SAM_USER_INFO_20));
1690                 if (ctr->info.id20 == NULL)
1691                         return NT_STATUS_NO_MEMORY;
1692                 if (!NT_STATUS_IS_OK(r_u->status = get_user_info_20(p->mem_ctx, ctr->info.id20, &info->sid)))
1693                         return r_u->status;
1694                 break;
1695
1696         case 21:
1697                 ctr->info.id21 = (SAM_USER_INFO_21 *)talloc_zero(p->mem_ctx,sizeof(SAM_USER_INFO_21));
1698                 if (ctr->info.id21 == NULL)
1699                         return NT_STATUS_NO_MEMORY;
1700                 if (!NT_STATUS_IS_OK(r_u->status = get_user_info_21(p->mem_ctx, ctr->info.id21, &info->sid)))
1701                         return r_u->status;
1702                 break;
1703
1704         default:
1705                 return NT_STATUS_INVALID_INFO_CLASS;
1706         }
1707
1708         init_samr_r_query_userinfo(r_u, ctr, r_u->status);
1709
1710         DEBUG(5,("_samr_query_userinfo: %d\n", __LINE__));
1711         
1712         return r_u->status;
1713 }
1714
1715 /*******************************************************************
1716  samr_reply_query_usergroups
1717  ********************************************************************/
1718
1719 NTSTATUS _samr_query_usergroups(pipes_struct *p, SAMR_Q_QUERY_USERGROUPS *q_u, SAMR_R_QUERY_USERGROUPS *r_u)
1720 {
1721         SAM_ACCOUNT *sam_pass=NULL;
1722         DOM_GID *gids = NULL;
1723         int num_groups = 0;
1724         struct samr_info *info = NULL;
1725         BOOL ret;
1726
1727         /*
1728          * from the SID in the request:
1729          * we should send back the list of DOMAIN GROUPS
1730          * the user is a member of
1731          *
1732          * and only the DOMAIN GROUPS
1733          * no ALIASES !!! neither aliases of the domain
1734          * nor aliases of the builtin SID
1735          *
1736          * JFM, 12/2/2001
1737          */
1738
1739         r_u->status = NT_STATUS_OK;
1740
1741         DEBUG(5,("_samr_query_usergroups: %d\n", __LINE__));
1742
1743         /* find the policy handle.  open a policy on it. */
1744         if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info))
1745                 return NT_STATUS_INVALID_HANDLE;
1746
1747         if (!sid_check_is_in_our_domain(&info->sid))
1748                 return NT_STATUS_OBJECT_TYPE_MISMATCH;
1749
1750         pdb_init_sam(&sam_pass);
1751         
1752         become_root();
1753         ret = pdb_getsampwsid(sam_pass, &info->sid);
1754         unbecome_root();
1755
1756         if (ret == False) {
1757                 pdb_free_sam(&sam_pass);
1758                 return NT_STATUS_NO_SUCH_USER;
1759         }
1760         
1761         if(!get_domain_user_groups(p->mem_ctx, &num_groups, &gids, sam_pass)) {
1762                 pdb_free_sam(&sam_pass);
1763                 return NT_STATUS_NO_SUCH_GROUP;
1764         }
1765         
1766         /* construct the response.  lkclXXXX: gids are not copied! */
1767         init_samr_r_query_usergroups(r_u, num_groups, gids, r_u->status);
1768         
1769         DEBUG(5,("_samr_query_usergroups: %d\n", __LINE__));
1770         
1771         pdb_free_sam(&sam_pass);
1772         
1773         return r_u->status;
1774 }
1775
1776 /*******************************************************************
1777  _samr_query_dom_info
1778  ********************************************************************/
1779
1780 NTSTATUS _samr_query_dom_info(pipes_struct *p, SAMR_Q_QUERY_DOMAIN_INFO *q_u, SAMR_R_QUERY_DOMAIN_INFO *r_u)
1781 {
1782         struct samr_info *info = NULL;
1783         SAM_UNK_CTR *ctr;
1784         uint32 min_pass_len,pass_hist,flag;
1785         time_t u_expire, u_min_age;
1786         NTTIME nt_expire, nt_min_age;
1787
1788         time_t u_lock_duration, u_reset_time;
1789         NTTIME nt_lock_duration, nt_reset_time;
1790         uint32 lockout;
1791         
1792         time_t u_logout;
1793         NTTIME nt_logout;
1794
1795         uint32 num_users=0, num_groups=0, num_aliases=0;
1796
1797         if ((ctr = (SAM_UNK_CTR *)talloc_zero(p->mem_ctx, sizeof(SAM_UNK_CTR))) == NULL)
1798                 return NT_STATUS_NO_MEMORY;
1799
1800         ZERO_STRUCTP(ctr);
1801
1802         r_u->status = NT_STATUS_OK;
1803         
1804         DEBUG(5,("_samr_query_dom_info: %d\n", __LINE__));
1805         
1806         /* find the policy handle.  open a policy on it. */
1807         if (!find_policy_by_hnd(p, &q_u->domain_pol, (void **)&info))
1808                 return NT_STATUS_INVALID_HANDLE;
1809         
1810         switch (q_u->switch_value) {
1811                 case 0x01:
1812                         account_policy_get(AP_MIN_PASSWORD_LEN, &min_pass_len);
1813                         account_policy_get(AP_PASSWORD_HISTORY, &pass_hist);
1814                         account_policy_get(AP_USER_MUST_LOGON_TO_CHG_PASS, &flag);
1815                         account_policy_get(AP_MAX_PASSWORD_AGE, (int *)&u_expire);
1816                         account_policy_get(AP_MIN_PASSWORD_AGE, (int *)&u_min_age);
1817
1818                         unix_to_nt_time_abs(&nt_expire, u_expire);
1819                         unix_to_nt_time_abs(&nt_min_age, u_min_age);
1820
1821                         init_unk_info1(&ctr->info.inf1, (uint16)min_pass_len, (uint16)pass_hist, 
1822                                        flag, nt_expire, nt_min_age);
1823                         break;
1824                 case 0x02:
1825                         become_root();          
1826                         r_u->status=load_sampwd_entries(info, ACB_NORMAL);
1827                         unbecome_root();
1828                         if (!NT_STATUS_IS_OK(r_u->status)) {
1829                                 DEBUG(5, ("_samr_query_dispinfo: load_sampwd_entries failed\n"));
1830                                 return r_u->status;
1831                         }
1832                         num_users=info->disp_info.num_user_account;
1833                         free_samr_db(info);
1834                         
1835                         r_u->status=load_group_domain_entries(info, get_global_sam_sid());
1836                         if (!NT_STATUS_IS_OK(r_u->status)) {
1837                                 DEBUG(5, ("_samr_query_dispinfo: load_group_domain_entries failed\n"));
1838                                 return r_u->status;
1839                         }
1840                         num_groups=info->disp_info.num_group_account;
1841                         free_samr_db(info);
1842                         
1843                         /* The time call below is to get a sequence number for the sam. FIXME !!! JRA. */
1844                         init_unk_info2(&ctr->info.inf2, global_myworkgroup, global_myname, (uint32) time(NULL), 
1845                                        num_users, num_groups, num_aliases);
1846                         break;
1847                 case 0x03:
1848                         account_policy_get(AP_TIME_TO_LOGOUT, (int *)&u_logout);
1849                         unix_to_nt_time_abs(&nt_logout, u_logout);
1850                         
1851                         init_unk_info3(&ctr->info.inf3, nt_logout);
1852                         break;
1853                 case 0x05:
1854                         init_unk_info5(&ctr->info.inf5, global_myname);
1855                         break;
1856                 case 0x06:
1857                         init_unk_info6(&ctr->info.inf6);
1858                         break;
1859                 case 0x07:
1860                         init_unk_info7(&ctr->info.inf7);
1861                         break;
1862                 case 0x0c:
1863                         account_policy_get(AP_LOCK_ACCOUNT_DURATION, (int *)&u_lock_duration);
1864                         account_policy_get(AP_RESET_COUNT_TIME, (int *)&u_reset_time);
1865                         account_policy_get(AP_BAD_ATTEMPT_LOCKOUT, &lockout);
1866         
1867                         unix_to_nt_time_abs(&nt_lock_duration, u_lock_duration);
1868                         unix_to_nt_time_abs(&nt_reset_time, u_reset_time);
1869         
1870                         init_unk_info12(&ctr->info.inf12, nt_lock_duration, nt_reset_time, (uint16)lockout);
1871                         break;
1872                 default:
1873                         return NT_STATUS_INVALID_INFO_CLASS;
1874                 }
1875         
1876         init_samr_r_query_dom_info(r_u, q_u->switch_value, ctr, NT_STATUS_OK);
1877         
1878         DEBUG(5,("_samr_query_dom_info: %d\n", __LINE__));
1879         
1880         return r_u->status;
1881 }
1882
1883 /*******************************************************************
1884  _api_samr_create_user
1885  Create an account, can be either a normal user or a machine.
1886  This funcion will need to be updated for bdc/domain trusts.
1887  ********************************************************************/
1888
1889 NTSTATUS _api_samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_CREATE_USER *r_u)
1890 {
1891         SAM_ACCOUNT *sam_pass=NULL;
1892         fstring account;
1893         DOM_SID sid;
1894         pstring add_script;
1895         POLICY_HND dom_pol = q_u->domain_pol;
1896         UNISTR2 user_account = q_u->uni_name;
1897         uint16 acb_info = q_u->acb_info;
1898         POLICY_HND *user_pol = &r_u->user_pol;
1899         struct samr_info *info = NULL;
1900         BOOL ret;
1901         NTSTATUS nt_status;
1902         struct passwd *pw;
1903
1904         /* find the policy handle.  open a policy on it. */
1905         if (!find_policy_by_hnd(p, &dom_pol, NULL))
1906                 return NT_STATUS_INVALID_HANDLE;
1907
1908         /* find the account: tell the caller if it exists.
1909           lkclXXXX i have *no* idea if this is a problem or not
1910           or even if you are supposed to construct a different
1911           reply if the account already exists...
1912          */
1913
1914         rpcstr_pull(account, user_account.buffer, sizeof(account), user_account.uni_str_len*2, 0);
1915         strlower(account);
1916
1917         pdb_init_sam(&sam_pass);
1918
1919         become_root();
1920         ret = pdb_getsampwnam(sam_pass, account);
1921         unbecome_root();
1922         if (ret == True) {
1923                 /* this account exists: say so */
1924                 pdb_free_sam(&sam_pass);
1925                 return NT_STATUS_USER_EXISTS;
1926         }
1927
1928         pdb_free_sam(&sam_pass);
1929
1930         /*
1931          * NB. VERY IMPORTANT ! This call must be done as the current pipe user,
1932          * *NOT* surrounded by a become_root()/unbecome_root() call. This ensures
1933          * that only people with write access to the smbpasswd file will be able
1934          * to create a user. JRA.
1935          */
1936
1937         /*
1938          * add the user in the /etc/passwd file or the unix authority system.
1939          * We don't check if the smb_create_user() function succed or not for 2 reasons:
1940          * a) local_password_change() checks for us if the /etc/passwd account really exists
1941          * b) smb_create_user() would return an error if the account already exists
1942          * and as it could return an error also if it can't create the account, it would be tricky.
1943          *
1944          * So we go the easy way, only check after if the account exists.
1945          * JFM (2/3/2001), to clear any possible bad understanding (-:
1946          *
1947          * We now have seperate script paramaters for adding users/machines so we
1948          * now have some sainity-checking to match. 
1949          */
1950
1951         DEBUG(10,("checking account %s at pos %d for $ termination\n",account, strlen(account)-1));
1952 #if 0
1953         if ((acb_info & ACB_WSTRUST) && (account[strlen(account)-1] == '$')) {
1954                 pstrcpy(add_script, lp_addmachine_script());            
1955         } else if ((!(acb_info & ACB_WSTRUST)) && (account[strlen(account)-1] != '$')) {
1956                 pstrcpy(add_script, lp_adduser_script());
1957         } else {
1958                 DEBUG(0, ("_api_samr_create_user: mismatch between trust flags and $ termination\n"));
1959                 pdb_free_sam(&sam_pass);
1960                 return NT_STATUS_UNSUCCESSFUL;
1961         }
1962 #endif
1963
1964         /* 
1965          * we can't check both the ending $ and the acb_info.
1966          * 
1967          * UserManager creates trust accounts (ending in $,
1968          * normal that hidden accounts) with the acb_info equals to ACB_NORMAL.
1969          * JFM, 11/29/2001
1970          */
1971         if (account[strlen(account)-1] == '$')
1972                 pstrcpy(add_script, lp_addmachine_script());            
1973         else 
1974                 pstrcpy(add_script, lp_adduser_script());
1975
1976         if(*add_script) {
1977                 int add_ret;
1978                 all_string_sub(add_script, "%u", account, sizeof(account));
1979                 add_ret = smbrun(add_script,NULL);
1980                 DEBUG(3,("_api_samr_create_user: Running the command `%s' gave %d\n", add_script, add_ret));
1981         }
1982         
1983         pw = getpwnam_alloc(account);
1984
1985         if (pw) {
1986                 if (!NT_STATUS_IS_OK(nt_status = pdb_init_sam_pw(&sam_pass, pw))) {
1987                         passwd_free(&pw);
1988                         return nt_status;
1989                 }
1990                 passwd_free(&pw); /* done with this now */
1991         } else {
1992                 DEBUG(3,("attempting to create non-unix account %s\n", account));
1993                 
1994                 if (!NT_STATUS_IS_OK(nt_status = pdb_init_sam(&sam_pass))) {
1995                         return nt_status;
1996                 }
1997                 
1998                 if (!pdb_set_username(sam_pass, account)) {
1999                         pdb_free_sam(&sam_pass);
2000                         return NT_STATUS_NO_MEMORY;
2001                 }
2002         }
2003
2004         pdb_set_acct_ctrl(sam_pass, acb_info);
2005  
2006         if (!pdb_add_sam_account(sam_pass)) {
2007                 pdb_free_sam(&sam_pass);
2008                 DEBUG(0, ("could not add user/computer %s to passdb.  Check permissions?\n", 
2009                           account));
2010                 return NT_STATUS_ACCESS_DENIED;         
2011         }
2012
2013         pdb_reset_sam(sam_pass);
2014         
2015         if (!pdb_getsampwnam(sam_pass, account)) {
2016                 pdb_free_sam(&sam_pass);
2017                 DEBUG(0, ("could not find user/computer %s just added to passdb?!?\n", 
2018                           account));
2019                 return NT_STATUS_ACCESS_DENIED;         
2020         }
2021         
2022         /* Get the user's SID */
2023         sid_copy(&sid, (DOM_SID *) pdb_get_user_sid(sam_pass));
2024         
2025         /* associate the user's SID with the new handle. */
2026         if ((info = get_samr_info_by_sid(&sid)) == NULL) {
2027                 pdb_free_sam(&sam_pass);
2028                 return NT_STATUS_NO_MEMORY;
2029         }
2030
2031         ZERO_STRUCTP(info);
2032         info->sid = sid;
2033
2034         /* get a (unique) handle.  open a policy on it. */
2035         if (!create_policy_hnd(p, user_pol, free_samr_info, (void *)info)) {
2036                 pdb_free_sam(&sam_pass);
2037                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2038         }
2039
2040         r_u->user_rid=pdb_get_user_rid(sam_pass);
2041         r_u->unknown_0 = 0x000703ff;
2042
2043         pdb_free_sam(&sam_pass);
2044
2045         return NT_STATUS_OK;
2046 }
2047
2048 /*******************************************************************
2049  samr_reply_connect_anon
2050  ********************************************************************/
2051
2052 NTSTATUS _samr_connect_anon(pipes_struct *p, SAMR_Q_CONNECT_ANON *q_u, SAMR_R_CONNECT_ANON *r_u)
2053 {
2054         struct samr_info *info = NULL;
2055
2056     /* Access check */
2057
2058     if (!pipe_access_check(p)) {
2059             DEBUG(3, ("access denied to samr_connect_anon\n"));
2060             r_u->status = NT_STATUS_ACCESS_DENIED;
2061             return r_u->status;
2062     }
2063
2064     /* set up the SAMR connect_anon response */
2065
2066     r_u->status = NT_STATUS_OK;
2067
2068     /* associate the user's SID with the new handle. */
2069     if ((info = get_samr_info_by_sid(NULL)) == NULL)
2070         return NT_STATUS_NO_MEMORY;
2071
2072     info->status = q_u->unknown_0;
2073
2074     /* get a (unique) handle.  open a policy on it. */
2075     if (!create_policy_hnd(p, &r_u->connect_pol, free_samr_info, (void *)info))
2076         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2077
2078     return r_u->status;
2079 }
2080
2081 /*******************************************************************
2082  samr_reply_connect
2083  ********************************************************************/
2084
2085 NTSTATUS _samr_connect(pipes_struct *p, SAMR_Q_CONNECT *q_u, SAMR_R_CONNECT *r_u)
2086 {
2087         struct samr_info *info = NULL;
2088
2089     DEBUG(5,("_samr_connect: %d\n", __LINE__));
2090
2091     /* Access check */
2092
2093     if (!pipe_access_check(p)) {
2094             DEBUG(3, ("access denied to samr_connect\n"));
2095             r_u->status = NT_STATUS_ACCESS_DENIED;
2096             return r_u->status;
2097     }
2098
2099     r_u->status = NT_STATUS_OK;
2100
2101     /* associate the user's SID with the new handle. */
2102         if ((info = get_samr_info_by_sid(NULL)) == NULL)
2103         return NT_STATUS_NO_MEMORY;
2104
2105     info->status = q_u->access_mask;
2106
2107     /* get a (unique) handle.  open a policy on it. */
2108     if (!create_policy_hnd(p, &r_u->connect_pol, free_samr_info, (void *)info))
2109         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2110
2111     DEBUG(5,("_samr_connect: %d\n", __LINE__));
2112
2113     return r_u->status;
2114 }
2115
2116 /**********************************************************************
2117  api_samr_lookup_domain
2118  **********************************************************************/
2119
2120 NTSTATUS _samr_lookup_domain(pipes_struct *p, SAMR_Q_LOOKUP_DOMAIN *q_u, SAMR_R_LOOKUP_DOMAIN *r_u)
2121 {
2122         fstring domain_name;
2123         DOM_SID sid;
2124
2125         r_u->status = NT_STATUS_OK;
2126
2127         if (!find_policy_by_hnd(p, &q_u->connect_pol, NULL))
2128                 return NT_STATUS_INVALID_HANDLE;
2129
2130         rpcstr_pull(domain_name, q_u->uni_domain.buffer, sizeof(domain_name), q_u->uni_domain.uni_str_len*2, 0);
2131
2132         ZERO_STRUCT(sid);
2133
2134         if (!secrets_fetch_domain_sid(domain_name, &sid)) {
2135                 r_u->status = NT_STATUS_NO_SUCH_DOMAIN;
2136         }
2137
2138         DEBUG(2,("Returning domain sid for domain %s -> %s\n", domain_name, sid_string_static(&sid)));
2139
2140         init_samr_r_lookup_domain(r_u, &sid, r_u->status);
2141
2142         return r_u->status;
2143 }
2144
2145 /******************************************************************
2146 makes a SAMR_R_ENUM_DOMAINS structure.
2147 ********************************************************************/
2148
2149 static BOOL make_enum_domains(TALLOC_CTX *ctx, SAM_ENTRY **pp_sam,
2150                         UNISTR2 **pp_uni_name, uint32 num_sam_entries, fstring doms[])
2151 {
2152         uint32 i;
2153         SAM_ENTRY *sam;
2154         UNISTR2 *uni_name;
2155
2156         DEBUG(5, ("make_enum_domains\n"));
2157
2158         *pp_sam = NULL;
2159         *pp_uni_name = NULL;
2160
2161         if (num_sam_entries == 0)
2162                 return True;
2163
2164         sam = (SAM_ENTRY *)talloc_zero(ctx, sizeof(SAM_ENTRY)*num_sam_entries);
2165         uni_name = (UNISTR2 *)talloc_zero(ctx, sizeof(UNISTR2)*num_sam_entries);
2166
2167         if (sam == NULL || uni_name == NULL)
2168                 return False;
2169
2170         for (i = 0; i < num_sam_entries; i++) {
2171                 int len = doms[i] != NULL ? strlen(doms[i]) : 0;
2172
2173                 init_sam_entry(&sam[i], len, 0);
2174                 init_unistr2(&uni_name[i], doms[i], len);
2175         }
2176
2177         *pp_sam = sam;
2178         *pp_uni_name = uni_name;
2179
2180         return True;
2181 }
2182
2183 /**********************************************************************
2184  api_samr_enum_domains
2185  **********************************************************************/
2186
2187 NTSTATUS _samr_enum_domains(pipes_struct *p, SAMR_Q_ENUM_DOMAINS *q_u, SAMR_R_ENUM_DOMAINS *r_u)
2188 {
2189         uint32 num_entries = 2;
2190         fstring dom[2];
2191         char *name;
2192
2193         r_u->status = NT_STATUS_OK;
2194
2195         switch (lp_server_role()) {
2196         case ROLE_DOMAIN_PDC:
2197         case ROLE_DOMAIN_BDC:
2198                 name = global_myworkgroup;
2199                 break;
2200         default:
2201                 name = global_myname;
2202         }
2203
2204         fstrcpy(dom[0],name);
2205         strupper(dom[0]);
2206         fstrcpy(dom[1],"Builtin");
2207
2208         if (!make_enum_domains(p->mem_ctx, &r_u->sam, &r_u->uni_dom_name, num_entries, dom))
2209                 return NT_STATUS_NO_MEMORY;
2210
2211         init_samr_r_enum_domains(r_u, q_u->start_idx + num_entries, num_entries);
2212
2213         return r_u->status;
2214 }
2215
2216 /*******************************************************************
2217  api_samr_open_alias
2218  ********************************************************************/
2219
2220 NTSTATUS _api_samr_open_alias(pipes_struct *p, SAMR_Q_OPEN_ALIAS *q_u, SAMR_R_OPEN_ALIAS *r_u)
2221 {
2222         DOM_SID sid;
2223         POLICY_HND domain_pol = q_u->dom_pol;
2224         uint32 alias_rid = q_u->rid_alias;
2225         POLICY_HND *alias_pol = &r_u->pol;
2226         struct samr_info *info = NULL;
2227
2228         r_u->status = NT_STATUS_OK;
2229
2230         /* get the domain policy. */
2231         if (!find_policy_by_hnd(p, &domain_pol, NULL))
2232                 return NT_STATUS_INVALID_HANDLE;
2233
2234         /* Get the domain SID stored in the domain policy */
2235         if(!get_lsa_policy_samr_sid(p, &domain_pol, &sid))
2236                 return NT_STATUS_INVALID_HANDLE;
2237
2238         /* append the alias' RID to it */
2239         if(!sid_append_rid(&sid, alias_rid))
2240                 return NT_STATUS_NO_SUCH_USER;
2241
2242         /*
2243          * we should check if the rid really exist !!!
2244          * JFM.
2245          */
2246
2247         /* associate the user's SID with the new handle. */
2248         if ((info = get_samr_info_by_sid(&sid)) == NULL)
2249                 return NT_STATUS_NO_MEMORY;
2250
2251         /* get a (unique) handle.  open a policy on it. */
2252         if (!create_policy_hnd(p, alias_pol, free_samr_info, (void *)info))
2253                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2254
2255         return r_u->status;
2256 }
2257
2258 /*******************************************************************
2259  set_user_info_10
2260  ********************************************************************/
2261
2262 static BOOL set_user_info_10(const SAM_USER_INFO_10 *id10, DOM_SID *sid)
2263 {
2264         SAM_ACCOUNT *pwd =NULL;
2265         BOOL ret;
2266         
2267         pdb_init_sam(&pwd);
2268         
2269         ret = pdb_getsampwsid(pwd, sid);
2270         
2271         if(ret==False) {
2272                 pdb_free_sam(&pwd);
2273                 return False;
2274         }
2275
2276         if (id10 == NULL) {
2277                 DEBUG(5, ("set_user_info_10: NULL id10\n"));
2278                 pdb_free_sam(&pwd);
2279                 return False;
2280         }
2281
2282         if (!pdb_set_acct_ctrl(pwd, id10->acb_info)) {
2283                 pdb_free_sam(&pwd);
2284                 return False;
2285         }
2286
2287         if(!pdb_update_sam_account(pwd)) {
2288                 pdb_free_sam(&pwd);
2289                 return False;
2290         }
2291
2292         pdb_free_sam(&pwd);
2293
2294         return True;
2295 }
2296
2297 /*******************************************************************
2298  set_user_info_12
2299  ********************************************************************/
2300
2301 static BOOL set_user_info_12(SAM_USER_INFO_12 *id12, DOM_SID *sid)
2302 {
2303         SAM_ACCOUNT *pwd = NULL;
2304
2305         pdb_init_sam(&pwd);
2306
2307         if(!pdb_getsampwsid(pwd, sid)) {
2308                 pdb_free_sam(&pwd);
2309                 return False;
2310         }
2311
2312         if (id12 == NULL) {
2313                 DEBUG(2, ("set_user_info_12: id12 is NULL\n"));
2314                 pdb_free_sam(&pwd);
2315                 return False;
2316         }
2317  
2318         if (!pdb_set_lanman_passwd (pwd, id12->lm_pwd)) {
2319                 pdb_free_sam(&pwd);
2320                 return False;
2321         }
2322         if (!pdb_set_nt_passwd     (pwd, id12->nt_pwd)) {
2323                 pdb_free_sam(&pwd);
2324                 return False;
2325         }
2326         if (!pdb_set_pass_changed_now (pwd)) {
2327                 pdb_free_sam(&pwd);
2328                 return False; 
2329         }
2330  
2331         if(!pdb_update_sam_account(pwd)) {
2332                 pdb_free_sam(&pwd);
2333                 return False;
2334         }
2335
2336         pdb_free_sam(&pwd);
2337         return True;
2338 }
2339
2340 /*******************************************************************
2341  set_user_info_21
2342  ********************************************************************/
2343
2344 static BOOL set_user_info_21(SAM_USER_INFO_21 *id21, DOM_SID *sid)
2345 {
2346         SAM_ACCOUNT *pwd = NULL;
2347  
2348         if (id21 == NULL) {
2349                 DEBUG(5, ("set_user_info_21: NULL id21\n"));
2350                 return False;
2351         }
2352  
2353         pdb_init_sam(&pwd);
2354  
2355         if (!pdb_getsampwsid(pwd, sid)) {
2356                 pdb_free_sam(&pwd);
2357                 return False;
2358         }
2359  
2360         copy_id21_to_sam_passwd(pwd, id21);
2361  
2362         /*
2363          * The funny part about the previous two calls is
2364          * that pwd still has the password hashes from the
2365          * passdb entry.  These have not been updated from
2366          * id21.  I don't know if they need to be set.    --jerry
2367          */
2368  
2369         /* write the change out */
2370         if(!pdb_update_sam_account(pwd)) {
2371                 pdb_free_sam(&pwd);
2372                 return False;
2373         }
2374
2375         pdb_free_sam(&pwd);
2376
2377         return True;
2378 }
2379
2380 /*******************************************************************
2381  set_user_info_23
2382  ********************************************************************/
2383
2384 static BOOL set_user_info_23(SAM_USER_INFO_23 *id23, DOM_SID *sid)
2385 {
2386         SAM_ACCOUNT *pwd = NULL;
2387         pstring plaintext_buf;
2388         uint32 len;
2389         uint16 acct_ctrl;
2390  
2391         if (id23 == NULL) {
2392                 DEBUG(5, ("set_user_info_23: NULL id23\n"));
2393                 return False;
2394         }
2395  
2396         pdb_init_sam(&pwd);
2397  
2398         if (!pdb_getsampwsid(pwd, sid)) {
2399                 pdb_free_sam(&pwd);
2400                 return False;
2401         }
2402
2403         DEBUG(5, ("Attempting administrator password change (level 23) for user %s\n",
2404                   pdb_get_username(pwd)));
2405
2406         acct_ctrl = pdb_get_acct_ctrl(pwd);
2407
2408         copy_id23_to_sam_passwd(pwd, id23);
2409  
2410         if (!decode_pw_buffer((char*)id23->pass, plaintext_buf, 256, &len)) {
2411                 pdb_free_sam(&pwd);
2412                 return False;
2413         }
2414   
2415         if (!pdb_set_plaintext_passwd (pwd, plaintext_buf)) {
2416                 pdb_free_sam(&pwd);
2417                 return False;
2418         }
2419  
2420         /* if it's a trust account, don't update /etc/passwd */
2421         if ( (!IS_SAM_UNIX_USER(pwd)) ||
2422                 ( (acct_ctrl &  ACB_DOMTRUST) == ACB_DOMTRUST ) ||
2423                 ( (acct_ctrl &  ACB_WSTRUST) ==  ACB_WSTRUST) ||
2424                 ( (acct_ctrl &  ACB_SVRTRUST) ==  ACB_SVRTRUST) ) {
2425                 DEBUG(5, ("Changing trust account or non-unix-user password, not updating /etc/passwd\n"));
2426         } else  {
2427                 /* update the UNIX password */
2428                 if (lp_unix_password_sync() )
2429                         if(!chgpasswd(pdb_get_username(pwd), "", plaintext_buf, True)) {
2430                                 pdb_free_sam(&pwd);
2431                                 return False;
2432                         }
2433         }
2434  
2435         ZERO_STRUCT(plaintext_buf);
2436  
2437         if(!pdb_update_sam_account(pwd)) {
2438                 pdb_free_sam(&pwd);
2439                 return False;
2440         }
2441  
2442         pdb_free_sam(&pwd);
2443
2444         return True;
2445 }
2446
2447 /*******************************************************************
2448  set_user_info_pw
2449  ********************************************************************/
2450
2451 static BOOL set_user_info_pw(char *pass, DOM_SID *sid)
2452 {
2453         SAM_ACCOUNT *pwd = NULL;
2454         uint32 len;
2455         pstring plaintext_buf;
2456         uint16 acct_ctrl;
2457  
2458         pdb_init_sam(&pwd);
2459  
2460         if (!pdb_getsampwsid(pwd, sid)) {
2461                 pdb_free_sam(&pwd);
2462                 return False;
2463         }
2464         
2465         DEBUG(5, ("Attempting administrator password change for user %s\n",
2466                   pdb_get_username(pwd)));
2467
2468         acct_ctrl = pdb_get_acct_ctrl(pwd);
2469
2470         ZERO_STRUCT(plaintext_buf);
2471  
2472         if (!decode_pw_buffer(pass, plaintext_buf, 256, &len)) {
2473                 pdb_free_sam(&pwd);
2474                 return False;
2475         }
2476
2477         if (!pdb_set_plaintext_passwd (pwd, plaintext_buf)) {
2478                 pdb_free_sam(&pwd);
2479                 return False;
2480         }
2481  
2482         /* if it's a trust account, don't update /etc/passwd */
2483         if ( (!IS_SAM_UNIX_USER(pwd)) ||
2484                 ( (acct_ctrl &  ACB_DOMTRUST) == ACB_DOMTRUST ) ||
2485                 ( (acct_ctrl &  ACB_WSTRUST) ==  ACB_WSTRUST) ||
2486                 ( (acct_ctrl &  ACB_SVRTRUST) ==  ACB_SVRTRUST) ) {
2487                 DEBUG(5, ("Changing trust account or non-unix-user password, not updating /etc/passwd\n"));
2488         } else {
2489                 /* update the UNIX password */
2490                 if (lp_unix_password_sync()) {
2491                         if(!chgpasswd(pdb_get_username(pwd), "", plaintext_buf, True)) {
2492                                 pdb_free_sam(&pwd);
2493                                 return False;
2494                         }
2495                 }
2496         }
2497  
2498         ZERO_STRUCT(plaintext_buf);
2499  
2500         DEBUG(5,("set_user_info_pw: pdb_update_pwd()\n"));
2501  
2502         /* update the SAMBA password */
2503         if(!pdb_update_sam_account(pwd)) {
2504                 pdb_free_sam(&pwd);
2505                 return False;
2506         }
2507
2508         pdb_free_sam(&pwd);
2509
2510         return True;
2511 }
2512
2513 /*******************************************************************
2514  samr_reply_set_userinfo
2515  ********************************************************************/
2516
2517 NTSTATUS _samr_set_userinfo(pipes_struct *p, SAMR_Q_SET_USERINFO *q_u, SAMR_R_SET_USERINFO *r_u)
2518 {
2519         DOM_SID sid;
2520         POLICY_HND *pol = &q_u->pol;
2521         uint16 switch_value = q_u->switch_value;
2522         SAM_USERINFO_CTR *ctr = q_u->ctr;
2523
2524         DEBUG(5, ("_samr_set_userinfo: %d\n", __LINE__));
2525
2526         r_u->status = NT_STATUS_OK;
2527
2528         /* find the policy handle.  open a policy on it. */
2529         if (!get_lsa_policy_samr_sid(p, pol, &sid))
2530                 return NT_STATUS_INVALID_HANDLE;
2531
2532         DEBUG(5, ("_samr_set_userinfo: sid:%s, level:%d\n", sid_string_static(&sid), switch_value));
2533
2534         if (ctr == NULL) {
2535                 DEBUG(5, ("_samr_set_userinfo: NULL info level\n"));
2536                 return NT_STATUS_INVALID_INFO_CLASS;
2537         }
2538
2539         /* ok!  user info levels (lots: see MSDEV help), off we go... */
2540         switch (switch_value) {
2541                 case 0x12:
2542                         if (!set_user_info_12(ctr->info.id12, &sid))
2543                                 return NT_STATUS_ACCESS_DENIED;
2544                         break;
2545
2546                 case 24:
2547                         SamOEMhash(ctr->info.id24->pass, p->session_key, 516);
2548
2549                         dump_data(100, (char *)ctr->info.id24->pass, 516);
2550
2551                         if (!set_user_info_pw((char *)ctr->info.id24->pass, &sid))
2552                                 return NT_STATUS_ACCESS_DENIED;
2553                         break;
2554
2555                 case 25:
2556 #if 0
2557                         /*
2558                          * Currently we don't really know how to unmarshall
2559                          * the level 25 struct, and the password encryption
2560                          * is different. This is a placeholder for when we
2561                          * do understand it. In the meantime just return INVALID
2562                          * info level and W2K SP2 drops down to level 23... JRA.
2563                          */
2564
2565                         SamOEMhash(ctr->info.id25->pass, p->session_key, 532);
2566
2567                         dump_data(100, (char *)ctr->info.id25->pass, 532);
2568
2569                         if (!set_user_info_pw(ctr->info.id25->pass, &sid))
2570                                 return NT_STATUS_ACCESS_DENIED;
2571                         break;
2572 #endif
2573                         return NT_STATUS_INVALID_INFO_CLASS;
2574
2575                 case 23:
2576                         SamOEMhash(ctr->info.id23->pass, p->session_key, 516);
2577
2578                         dump_data(100, (char *)ctr->info.id23->pass, 516);
2579
2580                         if (!set_user_info_23(ctr->info.id23, &sid))
2581                                 return NT_STATUS_ACCESS_DENIED;
2582                         break;
2583
2584                 default:
2585                         return NT_STATUS_INVALID_INFO_CLASS;
2586         }
2587
2588         return r_u->status;
2589 }
2590
2591 /*******************************************************************
2592  samr_reply_set_userinfo2
2593  ********************************************************************/
2594
2595 NTSTATUS _samr_set_userinfo2(pipes_struct *p, SAMR_Q_SET_USERINFO2 *q_u, SAMR_R_SET_USERINFO2 *r_u)
2596 {
2597         DOM_SID sid;
2598         SAM_USERINFO_CTR *ctr = q_u->ctr;
2599         POLICY_HND *pol = &q_u->pol;
2600         uint16 switch_value = q_u->switch_value;
2601
2602         DEBUG(5, ("samr_reply_set_userinfo2: %d\n", __LINE__));
2603
2604         r_u->status = NT_STATUS_OK;
2605
2606         /* find the policy handle.  open a policy on it. */
2607         if (!get_lsa_policy_samr_sid(p, pol, &sid))
2608                 return NT_STATUS_INVALID_HANDLE;
2609
2610         DEBUG(5, ("samr_reply_set_userinfo2: sid:%s\n", sid_string_static(&sid)));
2611
2612         if (ctr == NULL) {
2613                 DEBUG(5, ("samr_reply_set_userinfo2: NULL info level\n"));
2614                 return NT_STATUS_INVALID_INFO_CLASS;
2615         }
2616
2617         switch_value=ctr->switch_value;
2618
2619         /* ok!  user info levels (lots: see MSDEV help), off we go... */
2620         switch (switch_value) {
2621                 case 21:
2622                         if (!set_user_info_21(ctr->info.id21, &sid))
2623                                 return NT_STATUS_ACCESS_DENIED;
2624                         break;
2625                 case 16:
2626                         if (!set_user_info_10(ctr->info.id10, &sid))
2627                                 return NT_STATUS_ACCESS_DENIED;
2628                         break;
2629                 case 18:
2630                         /* Used by AS/U JRA. */
2631                         if (!set_user_info_12(ctr->info.id12, &sid))
2632                                 return NT_STATUS_ACCESS_DENIED;
2633                         break;
2634                 default:
2635                         return NT_STATUS_INVALID_INFO_CLASS;
2636         }
2637
2638         return r_u->status;
2639 }
2640
2641 /*********************************************************************
2642  _samr_query_aliasmem
2643 *********************************************************************/
2644
2645 NTSTATUS _samr_query_useraliases(pipes_struct *p, SAMR_Q_QUERY_USERALIASES *q_u, SAMR_R_QUERY_USERALIASES *r_u)
2646 {
2647         int num_groups = 0, tmp_num_groups=0;
2648         uint32 *rids=NULL, *new_rids=NULL, *tmp_rids=NULL;
2649         struct samr_info *info = NULL;
2650         int i,j;
2651         /* until i see a real useraliases query, we fack one up */
2652
2653         /* I have seen one, JFM 2/12/2001 */
2654         /*
2655          * Explanation of what this call does:
2656          * for all the SID given in the request:
2657          * return a list of alias (local groups)
2658          * that have those SID as members.
2659          *
2660          * and that's the alias in the domain specified
2661          * in the policy_handle
2662          *
2663          * if the policy handle is on an incorrect sid
2664          * for example a user's sid
2665          * we should reply NT_STATUS_OBJECT_TYPE_MISMATCH
2666          */
2667         
2668         r_u->status = NT_STATUS_OK;
2669
2670         DEBUG(5,("_samr_query_useraliases: %d\n", __LINE__));
2671
2672         /* find the policy handle.  open a policy on it. */
2673         if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info))
2674                 return NT_STATUS_INVALID_HANDLE;
2675
2676         if (!sid_check_is_domain(&info->sid) &&
2677             !sid_check_is_builtin(&info->sid))
2678                 return NT_STATUS_OBJECT_TYPE_MISMATCH;
2679
2680
2681         for (i=0; i<q_u->num_sids1; i++) {
2682
2683                 r_u->status=get_alias_user_groups(p->mem_ctx, &info->sid, &tmp_num_groups, &tmp_rids, &(q_u->sid[i].sid));
2684
2685                 /*
2686                  * if there is an error, we just continue as
2687                  * it can be an unfound user or group
2688                  */
2689                 if (!NT_STATUS_IS_OK(r_u->status)) {
2690                         DEBUG(10,("_samr_query_useraliases: an error occured while getting groups\n"));
2691                         continue;
2692                 }
2693
2694                 if (tmp_num_groups==0) {
2695                         DEBUG(10,("_samr_query_useraliases: no groups found\n"));
2696                         continue;
2697                 }
2698
2699                 new_rids=(uint32 *)talloc_realloc(p->mem_ctx, rids, (num_groups+tmp_num_groups)*sizeof(uint32));
2700                 if (new_rids==NULL) {
2701                         DEBUG(0,("_samr_query_useraliases: could not realloc memory\n"));
2702                         return NT_STATUS_NO_MEMORY;
2703                 }
2704                 rids=new_rids;
2705
2706                 for (j=0; j<tmp_num_groups; j++)
2707                         rids[j+num_groups]=tmp_rids[j];
2708                 
2709                 safe_free(tmp_rids);
2710                 
2711                 num_groups+=tmp_num_groups;
2712         }
2713         
2714         init_samr_r_query_useraliases(r_u, num_groups, rids, NT_STATUS_OK);
2715         return NT_STATUS_OK;
2716 }
2717
2718 /*********************************************************************
2719  _samr_query_aliasmem
2720 *********************************************************************/
2721
2722 NTSTATUS _samr_query_aliasmem(pipes_struct *p, SAMR_Q_QUERY_ALIASMEM *q_u, SAMR_R_QUERY_ALIASMEM *r_u)
2723 {
2724         int i;
2725
2726         GROUP_MAP map;
2727         int num_uids = 0;
2728         DOM_SID2 *sid;
2729         uid_t *uid=NULL;
2730
2731         DOM_SID alias_sid;
2732         DOM_SID als_sid;
2733         uint32 alias_rid;
2734         fstring alias_sid_str;
2735         DOM_SID temp_sid;
2736
2737         SAM_ACCOUNT *sam_user = NULL;
2738         BOOL check;
2739
2740         /* find the policy handle.  open a policy on it. */
2741         if (!get_lsa_policy_samr_sid(p, &q_u->alias_pol, &alias_sid)) 
2742                 return NT_STATUS_INVALID_HANDLE;
2743
2744         sid_copy(&als_sid, &alias_sid);
2745         sid_to_string(alias_sid_str, &alias_sid);
2746         sid_split_rid(&alias_sid, &alias_rid);
2747
2748         DEBUG(10, ("sid is %s\n", alias_sid_str));
2749
2750         if (sid_equal(&alias_sid, &global_sid_Builtin)) {
2751                 DEBUG(10, ("lookup on Builtin SID (S-1-5-32)\n"));
2752                 if(!get_local_group_from_sid(als_sid, &map, MAPPING_WITHOUT_PRIV))
2753                         return NT_STATUS_NO_SUCH_ALIAS;
2754         } else {
2755                 if (sid_equal(&alias_sid, get_global_sam_sid())) {
2756                         DEBUG(10, ("lookup on Server SID\n"));
2757                         if(!get_local_group_from_sid(als_sid, &map, MAPPING_WITHOUT_PRIV))
2758                                 return NT_STATUS_NO_SUCH_ALIAS;
2759                 }
2760         }
2761
2762         if(!get_uid_list_of_group(map.gid, &uid, &num_uids))
2763                 return NT_STATUS_NO_SUCH_ALIAS;
2764
2765         DEBUG(10, ("sid is %s\n", alias_sid_str));
2766         sid = (DOM_SID2 *)talloc_zero(p->mem_ctx, sizeof(DOM_SID2) * num_uids); 
2767         if (num_uids!=0 && sid == NULL) 
2768                 return NT_STATUS_NO_MEMORY;
2769
2770         for (i = 0; i < num_uids; i++) {
2771                 struct passwd *pass;
2772                 uint32 rid;
2773
2774                 sid_copy(&temp_sid, get_global_sam_sid());
2775
2776                 pass = getpwuid_alloc(uid[i]);
2777                 if (!pass) continue;
2778
2779                 if (!NT_STATUS_IS_OK(pdb_init_sam(&sam_user))) {
2780                         passwd_free(&pass);
2781                         continue;
2782                 }
2783
2784                 become_root();
2785                 check = pdb_getsampwnam(sam_user, pass->pw_name);
2786                 unbecome_root();
2787         
2788                 if (check != True) {
2789                         pdb_free_sam(&sam_user);
2790                         passwd_free(&pass);
2791                         continue;
2792                 }
2793         
2794                 rid = pdb_get_user_rid(sam_user);
2795                 if (rid == 0) {
2796                         pdb_free_sam(&sam_user);
2797                         passwd_free(&pass);
2798                         continue;
2799                 }
2800
2801                 pdb_free_sam(&sam_user);
2802                 passwd_free(&pass);
2803
2804                 sid_append_rid(&temp_sid, rid);
2805                 
2806                 init_dom_sid2(&sid[i], &temp_sid);
2807         }
2808
2809         DEBUG(10, ("sid is %s\n", alias_sid_str));
2810         init_samr_r_query_aliasmem(r_u, num_uids, sid, NT_STATUS_OK);
2811
2812         return NT_STATUS_OK;
2813 }
2814
2815 /*********************************************************************
2816  _samr_query_groupmem
2817 *********************************************************************/
2818
2819 NTSTATUS _samr_query_groupmem(pipes_struct *p, SAMR_Q_QUERY_GROUPMEM *q_u, SAMR_R_QUERY_GROUPMEM *r_u)
2820 {
2821         int num_uids = 0;
2822         int i;
2823         DOM_SID group_sid;
2824         uint32 group_rid;
2825         fstring group_sid_str;
2826         uid_t *uid=NULL;
2827         
2828         GROUP_MAP map;
2829
2830         uint32 *rid=NULL;
2831         uint32 *attr=NULL;
2832
2833         SAM_ACCOUNT *sam_user = NULL;
2834         BOOL check;
2835
2836
2837         /* find the policy handle.  open a policy on it. */
2838         if (!get_lsa_policy_samr_sid(p, &q_u->group_pol, &group_sid)) 
2839                 return NT_STATUS_INVALID_HANDLE;
2840
2841         /* todo: change to use sid_compare_front */
2842
2843         sid_split_rid(&group_sid, &group_rid);
2844         sid_to_string(group_sid_str, &group_sid);
2845         DEBUG(10, ("sid is %s\n", group_sid_str));
2846
2847         /* can we get a query for an SID outside our domain ? */
2848         if (!sid_equal(&group_sid, get_global_sam_sid()))
2849                 return NT_STATUS_NO_SUCH_GROUP;
2850
2851         sid_append_rid(&group_sid, group_rid);
2852         DEBUG(10, ("lookup on Domain SID\n"));
2853
2854         if(!get_domain_group_from_sid(group_sid, &map, MAPPING_WITHOUT_PRIV))
2855                 return NT_STATUS_NO_SUCH_GROUP;
2856
2857         if(!get_uid_list_of_group(map.gid, &uid, &num_uids))
2858                 return NT_STATUS_NO_SUCH_GROUP;
2859
2860         rid=talloc_zero(p->mem_ctx, sizeof(uint32)*num_uids);
2861         attr=talloc_zero(p->mem_ctx, sizeof(uint32)*num_uids);
2862         
2863         if (num_uids!=0 && (rid==NULL || attr==NULL))
2864                 return NT_STATUS_NO_MEMORY;
2865         
2866         for (i=0; i<num_uids; i++) {
2867                 struct passwd *pass;
2868                 uint32 urid;
2869
2870                 pass = getpwuid_alloc(uid[i]);
2871                 if (!pass) continue;
2872
2873                 if (!NT_STATUS_IS_OK(pdb_init_sam(&sam_user))) {
2874                         passwd_free(&pass);
2875                         continue;
2876                 }
2877
2878                 become_root();
2879                 check = pdb_getsampwnam(sam_user, pass->pw_name);
2880                 unbecome_root();
2881         
2882                 if (check != True) {
2883                         pdb_free_sam(&sam_user);
2884                         passwd_free(&pass);
2885                         continue;
2886                 }
2887         
2888                 urid = pdb_get_user_rid(sam_user);
2889                 if (urid == 0) {
2890                         pdb_free_sam(&sam_user);
2891                         passwd_free(&pass);
2892                         continue;
2893                 }
2894
2895                 pdb_free_sam(&sam_user);
2896                 passwd_free(&pass);
2897
2898                 rid[i] = urid;
2899                 attr[i] = SID_NAME_USER;                
2900         }
2901
2902         init_samr_r_query_groupmem(r_u, num_uids, rid, attr, NT_STATUS_OK);
2903
2904         return NT_STATUS_OK;
2905 }
2906
2907 /*********************************************************************
2908  _samr_add_aliasmem
2909 *********************************************************************/
2910
2911 NTSTATUS _samr_add_aliasmem(pipes_struct *p, SAMR_Q_ADD_ALIASMEM *q_u, SAMR_R_ADD_ALIASMEM *r_u)
2912 {
2913         DOM_SID alias_sid;
2914         fstring alias_sid_str;
2915         uid_t uid;
2916         struct passwd *pwd;
2917         struct group *grp;
2918         fstring grp_name;
2919         GROUP_MAP map;
2920         NTSTATUS ret;
2921         SAM_ACCOUNT *sam_user = NULL;
2922         BOOL check;
2923
2924         /* Find the policy handle. Open a policy on it. */
2925         if (!get_lsa_policy_samr_sid(p, &q_u->alias_pol, &alias_sid)) 
2926                 return NT_STATUS_INVALID_HANDLE;
2927
2928         sid_to_string(alias_sid_str, &alias_sid);
2929         DEBUG(10, ("sid is %s\n", alias_sid_str));
2930
2931         if (sid_compare(&alias_sid, get_global_sam_sid())>0) {
2932                 DEBUG(10, ("adding member on Server SID\n"));
2933                 if(!get_local_group_from_sid(alias_sid, &map, MAPPING_WITHOUT_PRIV))
2934                         return NT_STATUS_NO_SUCH_ALIAS;
2935         
2936         } else {
2937                 if (sid_compare(&alias_sid, &global_sid_Builtin)>0) {
2938                         DEBUG(10, ("adding member on BUILTIN SID\n"));
2939                         if( !get_local_group_from_sid(alias_sid, &map, MAPPING_WITHOUT_PRIV))
2940                                 return NT_STATUS_NO_SUCH_ALIAS;
2941
2942                 } else
2943                         return NT_STATUS_NO_SUCH_ALIAS;
2944         }
2945
2946         ret = pdb_init_sam(&sam_user);
2947         if (!NT_STATUS_IS_OK(ret))
2948                 return ret;
2949         
2950         check = pdb_getsampwsid(sam_user, &q_u->sid.sid);
2951         
2952         if (check != True) {
2953                 pdb_free_sam(&sam_user);
2954                 return NT_STATUS_NO_SUCH_USER;
2955         }
2956         
2957         uid = pdb_get_uid(sam_user);
2958         if (uid == -1) {
2959                 pdb_free_sam(&sam_user);
2960                 return NT_STATUS_NO_SUCH_USER;
2961         }
2962
2963         pdb_free_sam(&sam_user);
2964
2965         if ((pwd=getpwuid_alloc(uid)) == NULL) {
2966                 return NT_STATUS_NO_SUCH_USER;
2967         } else {
2968                 passwd_free(&pwd);
2969         }
2970
2971         if ((grp=getgrgid(map.gid)) == NULL)
2972                 return NT_STATUS_NO_SUCH_ALIAS;
2973
2974         /* we need to copy the name otherwise it's overloaded in user_in_group_list */
2975         fstrcpy(grp_name, grp->gr_name);
2976
2977         /* if the user is already in the group */
2978         if(user_in_group_list(pwd->pw_name, grp_name))
2979                 return NT_STATUS_MEMBER_IN_ALIAS;
2980
2981         /* 
2982          * ok, the group exist, the user exist, the user is not in the group,
2983          * we can (finally) add it to the group !
2984          */
2985         smb_add_user_group(grp_name, pwd->pw_name);
2986
2987         /* check if the user has been added then ... */
2988         if(!user_in_group_list(pwd->pw_name, grp_name))
2989                 return NT_STATUS_MEMBER_NOT_IN_ALIAS;   /* don't know what to reply else */
2990
2991         return NT_STATUS_OK;
2992 }
2993
2994 /*********************************************************************
2995  _samr_del_aliasmem
2996 *********************************************************************/
2997
2998 NTSTATUS _samr_del_aliasmem(pipes_struct *p, SAMR_Q_DEL_ALIASMEM *q_u, SAMR_R_DEL_ALIASMEM *r_u)
2999 {
3000         DOM_SID alias_sid;
3001         fstring alias_sid_str;
3002         struct group *grp;
3003         fstring grp_name;
3004         GROUP_MAP map;
3005         SAM_ACCOUNT *sam_pass=NULL;
3006
3007         /* Find the policy handle. Open a policy on it. */
3008         if (!get_lsa_policy_samr_sid(p, &q_u->alias_pol, &alias_sid)) 
3009                 return NT_STATUS_INVALID_HANDLE;
3010
3011         sid_to_string(alias_sid_str, &alias_sid);
3012         DEBUG(10, ("_samr_del_aliasmem:sid is %s\n", alias_sid_str));
3013
3014         if (!sid_check_is_in_our_domain(&alias_sid) &&
3015             !sid_check_is_in_builtin(&alias_sid)) {
3016                 DEBUG(10, ("_samr_del_aliasmem:invalid alias group\n"));
3017                 return NT_STATUS_NO_SUCH_ALIAS;
3018         }
3019
3020         if( !get_local_group_from_sid(alias_sid, &map, MAPPING_WITHOUT_PRIV))
3021                 return NT_STATUS_NO_SUCH_ALIAS;
3022
3023         if ((grp=getgrgid(map.gid)) == NULL)
3024                 return NT_STATUS_NO_SUCH_ALIAS;
3025
3026         /* we need to copy the name otherwise it's overloaded in user_in_group_list */
3027         fstrcpy(grp_name, grp->gr_name);
3028
3029         /* check if the user exists before trying to remove it from the group */
3030         pdb_init_sam(&sam_pass);
3031         if(!pdb_getsampwsid(sam_pass, &q_u->sid.sid)) {
3032                 DEBUG(5,("_samr_del_aliasmem:User %s doesn't exist.\n", pdb_get_username(sam_pass)));
3033                 pdb_free_sam(&sam_pass);
3034                 return NT_STATUS_NO_SUCH_USER;
3035         }
3036
3037         /* if the user is not in the group */
3038         if(!user_in_group_list(pdb_get_username(sam_pass), grp_name)) {
3039                 pdb_free_sam(&sam_pass);
3040                 return NT_STATUS_MEMBER_IN_ALIAS;
3041         }
3042
3043         smb_delete_user_group(grp_name, pdb_get_username(sam_pass));
3044
3045         /* check if the user has been removed then ... */
3046         if(user_in_group_list(pdb_get_username(sam_pass), grp_name)) {
3047                 pdb_free_sam(&sam_pass);
3048                 return NT_STATUS_MEMBER_NOT_IN_ALIAS;   /* don't know what to reply else */
3049         }
3050
3051         pdb_free_sam(&sam_pass);
3052         return NT_STATUS_OK;
3053 }
3054
3055 /*********************************************************************
3056  _samr_add_groupmem
3057 *********************************************************************/
3058
3059 NTSTATUS _samr_add_groupmem(pipes_struct *p, SAMR_Q_ADD_GROUPMEM *q_u, SAMR_R_ADD_GROUPMEM *r_u)
3060 {
3061         DOM_SID group_sid;
3062         DOM_SID user_sid;
3063         fstring group_sid_str;
3064         struct passwd *pwd;
3065         struct group *grp;
3066         fstring grp_name;
3067         GROUP_MAP map;
3068         uid_t uid;
3069         NTSTATUS ret;
3070         SAM_ACCOUNT *sam_user;
3071         BOOL check;
3072
3073         /* Find the policy handle. Open a policy on it. */
3074         if (!get_lsa_policy_samr_sid(p, &q_u->pol, &group_sid)) 
3075                 return NT_STATUS_INVALID_HANDLE;
3076
3077         sid_to_string(group_sid_str, &group_sid);
3078         DEBUG(10, ("sid is %s\n", group_sid_str));
3079
3080         if (sid_compare(&group_sid, get_global_sam_sid())<=0)
3081                 return NT_STATUS_NO_SUCH_GROUP;
3082
3083         DEBUG(10, ("lookup on Domain SID\n"));
3084
3085         if(!get_domain_group_from_sid(group_sid, &map, MAPPING_WITHOUT_PRIV))
3086                 return NT_STATUS_NO_SUCH_GROUP;
3087
3088         sid_copy(&user_sid, get_global_sam_sid());
3089         sid_append_rid(&user_sid, q_u->rid);
3090
3091         ret = pdb_init_sam(&sam_user);
3092         if (!NT_STATUS_IS_OK(ret))
3093                 return ret;
3094         
3095         check = pdb_getsampwsid(sam_user, &user_sid);
3096         
3097         if (check != True) {
3098                 pdb_free_sam(&sam_user);
3099                 return NT_STATUS_NO_SUCH_USER;
3100         }
3101         
3102         uid = pdb_get_uid(sam_user);
3103         if (uid == -1) {
3104                 pdb_free_sam(&sam_user);
3105                 return NT_STATUS_NO_SUCH_USER;
3106         }
3107
3108         pdb_free_sam(&sam_user);
3109
3110         if ((pwd=getpwuid_alloc(uid)) == NULL) {
3111                 return NT_STATUS_NO_SUCH_USER;
3112         } else {
3113                 passwd_free(&pwd);
3114         }
3115
3116         if ((grp=getgrgid(map.gid)) == NULL)
3117                 return NT_STATUS_NO_SUCH_GROUP;
3118
3119         /* we need to copy the name otherwise it's overloaded in user_in_group_list */
3120         fstrcpy(grp_name, grp->gr_name);
3121
3122         /* if the user is already in the group */
3123         if(user_in_group_list(pwd->pw_name, grp_name))
3124                 return NT_STATUS_MEMBER_IN_GROUP;
3125
3126         /* 
3127          * ok, the group exist, the user exist, the user is not in the group,
3128          *
3129          * we can (finally) add it to the group !
3130          */
3131
3132         smb_add_user_group(grp_name, pwd->pw_name);
3133
3134         /* check if the user has been added then ... */
3135         if(!user_in_group_list(pwd->pw_name, grp_name))
3136                 return NT_STATUS_MEMBER_NOT_IN_GROUP;           /* don't know what to reply else */
3137
3138         return NT_STATUS_OK;
3139 }
3140
3141 /*********************************************************************
3142  _samr_del_groupmem
3143 *********************************************************************/
3144
3145 NTSTATUS _samr_del_groupmem(pipes_struct *p, SAMR_Q_DEL_GROUPMEM *q_u, SAMR_R_DEL_GROUPMEM *r_u)
3146 {
3147         DOM_SID group_sid;
3148         DOM_SID user_sid;
3149         SAM_ACCOUNT *sam_pass=NULL;
3150         GROUP_MAP map;
3151         fstring grp_name;
3152         struct group *grp;
3153
3154         /*
3155          * delete the group member named q_u->rid
3156          * who is a member of the sid associated with the handle
3157          * the rid is a user's rid as the group is a domain group.
3158          */
3159
3160         /* Find the policy handle. Open a policy on it. */
3161         if (!get_lsa_policy_samr_sid(p, &q_u->pol, &group_sid)) 
3162                 return NT_STATUS_INVALID_HANDLE;
3163
3164         if(!sid_check_is_in_our_domain(&group_sid))
3165                 return NT_STATUS_NO_SUCH_GROUP;
3166
3167         sid_copy(&user_sid, get_global_sam_sid());
3168         sid_append_rid(&user_sid, q_u->rid);
3169
3170         if(!get_domain_group_from_sid(group_sid, &map, MAPPING_WITHOUT_PRIV))
3171                 return NT_STATUS_NO_SUCH_GROUP;
3172
3173         if ((grp=getgrgid(map.gid)) == NULL)
3174                 return NT_STATUS_NO_SUCH_GROUP;
3175
3176         /* we need to copy the name otherwise it's overloaded in user_in_group_list */
3177         fstrcpy(grp_name, grp->gr_name);
3178
3179         /* check if the user exists before trying to remove it from the group */
3180         pdb_init_sam(&sam_pass);
3181         if(!pdb_getsampwsid(sam_pass, &user_sid)) {
3182                 DEBUG(5,("User %s doesn't exist.\n", pdb_get_username(sam_pass)));
3183                 pdb_free_sam(&sam_pass);
3184                 return NT_STATUS_NO_SUCH_USER;
3185         }
3186
3187         /* if the user is not in the group */
3188         if(!user_in_group_list(pdb_get_username(sam_pass), grp_name)) {
3189                 pdb_free_sam(&sam_pass);
3190                 return NT_STATUS_MEMBER_NOT_IN_GROUP;
3191         }
3192
3193         smb_delete_user_group(grp_name, pdb_get_username(sam_pass));
3194
3195         /* check if the user has been removed then ... */
3196         if(user_in_group_list(pdb_get_username(sam_pass), grp_name)) {
3197                 pdb_free_sam(&sam_pass);
3198                 return NT_STATUS_ACCESS_DENIED;         /* don't know what to reply else */
3199         }
3200         
3201         pdb_free_sam(&sam_pass);
3202         return NT_STATUS_OK;
3203
3204 }
3205
3206 /****************************************************************************
3207  Delete a UNIX user on demand.
3208 ****************************************************************************/
3209
3210 static int smb_delete_user(const char *unix_user)
3211 {
3212         pstring del_script;
3213         int ret;
3214
3215         pstrcpy(del_script, lp_deluser_script());
3216         if (! *del_script)
3217                 return -1;
3218         all_string_sub(del_script, "%u", unix_user, sizeof(pstring));
3219         ret = smbrun(del_script,NULL);
3220         DEBUG(3,("smb_delete_user: Running the command `%s' gave %d\n",del_script,ret));
3221         return ret;
3222 }
3223
3224 /*********************************************************************
3225  _samr_delete_dom_user
3226 *********************************************************************/
3227
3228 NTSTATUS _samr_delete_dom_user(pipes_struct *p, SAMR_Q_DELETE_DOM_USER *q_u, SAMR_R_DELETE_DOM_USER *r_u )
3229 {
3230         DOM_SID user_sid;
3231         SAM_ACCOUNT *sam_pass=NULL;
3232
3233         DEBUG(5, ("_samr_delete_dom_user: %d\n", __LINE__));
3234
3235         /* Find the policy handle. Open a policy on it. */
3236         if (!get_lsa_policy_samr_sid(p, &q_u->user_pol, &user_sid)) 
3237                 return NT_STATUS_INVALID_HANDLE;
3238
3239         if (!sid_check_is_in_our_domain(&user_sid))
3240                 return NT_STATUS_CANNOT_DELETE;
3241
3242         /* check if the user exists before trying to delete */
3243         pdb_init_sam(&sam_pass);
3244         if(!pdb_getsampwsid(sam_pass, &user_sid)) {
3245                 DEBUG(5,("_samr_delete_dom_user:User %s doesn't exist.\n", pdb_get_username(sam_pass)));
3246                 pdb_free_sam(&sam_pass);
3247                 return NT_STATUS_NO_SUCH_USER;
3248         }
3249
3250         /* delete the unix side */
3251         /*
3252          * note: we don't check if the delete really happened
3253          * as the script is not necessary present
3254          * and maybe the sysadmin doesn't want to delete the unix side
3255          */
3256         smb_delete_user(pdb_get_username(sam_pass));
3257
3258         /* and delete the samba side */
3259         if (!pdb_delete_sam_account(sam_pass)) {
3260                 DEBUG(5,("_samr_delete_dom_user:Failed to delete entry for user %s.\n", pdb_get_username(sam_pass)));
3261                 pdb_free_sam(&sam_pass);
3262                 return NT_STATUS_CANNOT_DELETE;
3263         }
3264         
3265         pdb_free_sam(&sam_pass);
3266
3267         if (!close_policy_hnd(p, &q_u->user_pol))
3268                 return NT_STATUS_OBJECT_NAME_INVALID;
3269
3270         return NT_STATUS_OK;
3271 }
3272
3273 /*********************************************************************
3274  _samr_delete_dom_group
3275 *********************************************************************/
3276
3277 NTSTATUS _samr_delete_dom_group(pipes_struct *p, SAMR_Q_DELETE_DOM_GROUP *q_u, SAMR_R_DELETE_DOM_GROUP *r_u)
3278 {
3279         DOM_SID group_sid;
3280         DOM_SID dom_sid;
3281         uint32 group_rid;
3282         fstring group_sid_str;
3283         gid_t gid;
3284         struct group *grp;
3285         GROUP_MAP map;
3286
3287         DEBUG(5, ("samr_delete_dom_group: %d\n", __LINE__));
3288
3289         /* Find the policy handle. Open a policy on it. */
3290         if (!get_lsa_policy_samr_sid(p, &q_u->group_pol, &group_sid)) 
3291                 return NT_STATUS_INVALID_HANDLE;
3292
3293         sid_copy(&dom_sid, &group_sid);
3294         sid_to_string(group_sid_str, &dom_sid);
3295         sid_split_rid(&dom_sid, &group_rid);
3296
3297         DEBUG(10, ("sid is %s\n", group_sid_str));
3298
3299         /* we check if it's our SID before deleting */
3300         if (!sid_equal(&dom_sid, get_global_sam_sid()))
3301                 return NT_STATUS_NO_SUCH_GROUP;
3302
3303         DEBUG(10, ("lookup on Domain SID\n"));
3304
3305         if(!get_domain_group_from_sid(group_sid, &map, MAPPING_WITHOUT_PRIV))
3306                 return NT_STATUS_NO_SUCH_GROUP;
3307
3308         gid=map.gid;
3309
3310         /* check if group really exists */
3311         if ( (grp=getgrgid(gid)) == NULL)
3312                 return NT_STATUS_NO_SUCH_GROUP;
3313
3314         /* we can delete the UNIX group */
3315         smb_delete_group(grp->gr_name);
3316
3317         /* check if the group has been successfully deleted */
3318         if ( (grp=getgrgid(gid)) != NULL)
3319                 return NT_STATUS_ACCESS_DENIED;
3320
3321         if(!group_map_remove(group_sid))
3322                 return NT_STATUS_ACCESS_DENIED;
3323
3324         if (!close_policy_hnd(p, &q_u->group_pol))
3325                 return NT_STATUS_OBJECT_NAME_INVALID;
3326
3327         return NT_STATUS_OK;
3328 }
3329
3330 /*********************************************************************
3331  _samr_delete_dom_alias
3332 *********************************************************************/
3333
3334 NTSTATUS _samr_delete_dom_alias(pipes_struct *p, SAMR_Q_DELETE_DOM_ALIAS *q_u, SAMR_R_DELETE_DOM_ALIAS *r_u)
3335 {
3336         DOM_SID alias_sid;
3337         DOM_SID dom_sid;
3338         uint32 alias_rid;
3339         fstring alias_sid_str;
3340         gid_t gid;
3341         struct group *grp;
3342         GROUP_MAP map;
3343
3344         DEBUG(5, ("_samr_delete_dom_alias: %d\n", __LINE__));
3345
3346         /* Find the policy handle. Open a policy on it. */
3347         if (!get_lsa_policy_samr_sid(p, &q_u->alias_pol, &alias_sid)) 
3348                 return NT_STATUS_INVALID_HANDLE;
3349
3350         sid_copy(&dom_sid, &alias_sid);
3351         sid_to_string(alias_sid_str, &dom_sid);
3352         sid_split_rid(&dom_sid, &alias_rid);
3353
3354         DEBUG(10, ("sid is %s\n", alias_sid_str));
3355
3356         /* we check if it's our SID before deleting */
3357         if (!sid_equal(&dom_sid, get_global_sam_sid()))
3358                 return NT_STATUS_NO_SUCH_ALIAS;
3359
3360         DEBUG(10, ("lookup on Local SID\n"));
3361
3362         if(!get_local_group_from_sid(alias_sid, &map, MAPPING_WITHOUT_PRIV))
3363                 return NT_STATUS_NO_SUCH_ALIAS;
3364
3365         gid=map.gid;
3366
3367         /* check if group really exists */
3368         if ( (grp=getgrgid(gid)) == NULL)
3369                 return NT_STATUS_NO_SUCH_ALIAS;
3370
3371         /* we can delete the UNIX group */
3372         smb_delete_group(grp->gr_name);
3373
3374         /* check if the group has been successfully deleted */
3375         if ( (grp=getgrgid(gid)) != NULL)
3376                 return NT_STATUS_ACCESS_DENIED;
3377
3378         /* don't check if we removed it as it could be an un-mapped group */
3379         group_map_remove(alias_sid);
3380
3381         if (!close_policy_hnd(p, &q_u->alias_pol))
3382                 return NT_STATUS_OBJECT_NAME_INVALID;
3383
3384         return NT_STATUS_OK;
3385 }
3386
3387 /*********************************************************************
3388  _samr_create_dom_group
3389 *********************************************************************/
3390
3391 NTSTATUS _samr_create_dom_group(pipes_struct *p, SAMR_Q_CREATE_DOM_GROUP *q_u, SAMR_R_CREATE_DOM_GROUP *r_u)
3392 {
3393         DOM_SID dom_sid;
3394         DOM_SID info_sid;
3395         fstring name;
3396         fstring sid_string;
3397         struct group *grp;
3398         struct samr_info *info;
3399         PRIVILEGE_SET priv_set;
3400
3401         init_privilege(&priv_set);
3402
3403         /* Find the policy handle. Open a policy on it. */
3404         if (!get_lsa_policy_samr_sid(p, &q_u->pol, &dom_sid)) 
3405                 return NT_STATUS_INVALID_HANDLE;
3406
3407         if (!sid_equal(&dom_sid, get_global_sam_sid()))
3408                 return NT_STATUS_ACCESS_DENIED;
3409
3410         /* TODO: check if allowed to create group and add a become_root/unbecome_root pair.*/
3411
3412         unistr2_to_ascii(name, &q_u->uni_acct_desc, sizeof(name)-1);
3413
3414         /* check if group already exist */
3415         if ((grp=getgrnam(name)) != NULL)
3416                 return NT_STATUS_GROUP_EXISTS;
3417
3418         /* we can create the UNIX group */
3419         smb_create_group(name);
3420
3421         /* check if the group has been successfully created */
3422         if ((grp=getgrnam(name)) == NULL)
3423                 return NT_STATUS_ACCESS_DENIED;
3424
3425         r_u->rid=pdb_gid_to_group_rid(grp->gr_gid);
3426
3427         /* add the group to the mapping table */
3428         sid_copy(&info_sid, get_global_sam_sid());
3429         sid_append_rid(&info_sid, r_u->rid);
3430         sid_to_string(sid_string, &info_sid);
3431
3432         if(!add_initial_entry(grp->gr_gid, sid_string, SID_NAME_DOM_GRP, name, NULL, priv_set, PR_ACCESS_FROM_NETWORK))
3433                 return NT_STATUS_ACCESS_DENIED;
3434
3435         if ((info = get_samr_info_by_sid(&info_sid)) == NULL)
3436                 return NT_STATUS_NO_MEMORY;
3437
3438         /* get a (unique) handle.  open a policy on it. */
3439         if (!create_policy_hnd(p, &r_u->pol, free_samr_info, (void *)info))
3440                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3441
3442         return NT_STATUS_OK;
3443 }
3444
3445 /*********************************************************************
3446  _samr_create_dom_alias
3447 *********************************************************************/
3448
3449 NTSTATUS _samr_create_dom_alias(pipes_struct *p, SAMR_Q_CREATE_DOM_ALIAS *q_u, SAMR_R_CREATE_DOM_ALIAS *r_u)
3450 {
3451         DOM_SID dom_sid;
3452         DOM_SID info_sid;
3453         fstring name;
3454         fstring sid_string;
3455         struct group *grp;
3456         struct samr_info *info;
3457         PRIVILEGE_SET priv_set;
3458
3459         init_privilege(&priv_set);
3460
3461         /* Find the policy handle. Open a policy on it. */
3462         if (!get_lsa_policy_samr_sid(p, &q_u->dom_pol, &dom_sid)) 
3463                 return NT_STATUS_INVALID_HANDLE;
3464
3465         if (!sid_equal(&dom_sid, get_global_sam_sid()))
3466                 return NT_STATUS_ACCESS_DENIED;
3467
3468         /* TODO: check if allowed to create group  and add a become_root/unbecome_root pair.*/
3469
3470         unistr2_to_ascii(name, &q_u->uni_acct_desc, sizeof(name)-1);
3471
3472         /* check if group already exists */
3473         if ( (grp=getgrnam(name)) != NULL)
3474                 return NT_STATUS_GROUP_EXISTS;
3475
3476         /* we can create the UNIX group */
3477         smb_create_group(name);
3478
3479         /* check if the group has been successfully created */
3480         if ((grp=getgrnam(name)) == NULL)
3481                 return NT_STATUS_ACCESS_DENIED;
3482
3483         r_u->rid=pdb_gid_to_group_rid(grp->gr_gid);
3484
3485         sid_copy(&info_sid, get_global_sam_sid());
3486         sid_append_rid(&info_sid, r_u->rid);
3487         sid_to_string(sid_string, &info_sid);
3488
3489         /* add the group to the mapping table */
3490         if(!add_initial_entry(grp->gr_gid, sid_string, SID_NAME_ALIAS, name, NULL, priv_set, PR_ACCESS_FROM_NETWORK))
3491                 return NT_STATUS_ACCESS_DENIED;
3492
3493         if ((info = get_samr_info_by_sid(&info_sid)) == NULL)
3494                 return NT_STATUS_NO_MEMORY;
3495
3496         /* get a (unique) handle.  open a policy on it. */
3497         if (!create_policy_hnd(p, &r_u->alias_pol, free_samr_info, (void *)info))
3498                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3499
3500         return NT_STATUS_OK;
3501 }
3502
3503 /*********************************************************************
3504  _samr_query_groupinfo
3505
3506 sends the name/comment pair of a domain group
3507 level 1 send also the number of users of that group
3508 *********************************************************************/
3509
3510 NTSTATUS _samr_query_groupinfo(pipes_struct *p, SAMR_Q_QUERY_GROUPINFO *q_u, SAMR_R_QUERY_GROUPINFO *r_u)
3511 {
3512         DOM_SID group_sid;
3513         GROUP_MAP map;
3514         uid_t *uid=NULL;
3515         int num_uids=0;
3516         GROUP_INFO_CTR *ctr;
3517
3518         if (!get_lsa_policy_samr_sid(p, &q_u->pol, &group_sid)) 
3519                 return NT_STATUS_INVALID_HANDLE;
3520
3521         if (!get_domain_group_from_sid(group_sid, &map, MAPPING_WITHOUT_PRIV))
3522                 return NT_STATUS_INVALID_HANDLE;
3523
3524         ctr=(GROUP_INFO_CTR *)talloc_zero(p->mem_ctx, sizeof(GROUP_INFO_CTR));
3525         if (ctr==NULL)
3526                 return NT_STATUS_NO_MEMORY;
3527
3528         switch (q_u->switch_level) {
3529                 case 1:
3530                         ctr->switch_value1 = 1;
3531                         if(!get_uid_list_of_group(map.gid, &uid, &num_uids))
3532                                 return NT_STATUS_NO_SUCH_GROUP;
3533                         init_samr_group_info1(&ctr->group.info1, map.nt_name, map.comment, num_uids);
3534                         SAFE_FREE(uid);
3535                         break;
3536                 case 3:
3537                         ctr->switch_value1 = 3;
3538                         init_samr_group_info3(&ctr->group.info3);
3539                         break;
3540                 case 4:
3541                         ctr->switch_value1 = 4;
3542                         init_samr_group_info4(&ctr->group.info4, map.comment);
3543                         break;
3544                 default:
3545                         return NT_STATUS_INVALID_INFO_CLASS;
3546         }
3547
3548         init_samr_r_query_groupinfo(r_u, ctr, NT_STATUS_OK);
3549
3550         return NT_STATUS_OK;
3551 }
3552
3553 /*********************************************************************
3554  _samr_set_groupinfo
3555  
3556  update a domain group's comment.
3557 *********************************************************************/
3558
3559 NTSTATUS _samr_set_groupinfo(pipes_struct *p, SAMR_Q_SET_GROUPINFO *q_u, SAMR_R_SET_GROUPINFO *r_u)
3560 {
3561         DOM_SID group_sid;
3562         GROUP_MAP map;
3563         GROUP_INFO_CTR *ctr;
3564
3565         if (!get_lsa_policy_samr_sid(p, &q_u->pol, &group_sid)) 
3566                 return NT_STATUS_INVALID_HANDLE;
3567
3568         if (!get_domain_group_from_sid(group_sid, &map, MAPPING_WITH_PRIV))
3569                 return NT_STATUS_NO_SUCH_GROUP;
3570         
3571         ctr=q_u->ctr;
3572
3573         switch (ctr->switch_value1) {
3574                 case 1:
3575                         unistr2_to_ascii(map.comment, &(ctr->group.info1.uni_acct_desc), sizeof(map.comment)-1);
3576                         break;
3577                 case 4:
3578                         unistr2_to_ascii(map.comment, &(ctr->group.info4.uni_acct_desc), sizeof(map.comment)-1);
3579                         break;
3580                 default:
3581                         free_privilege(&map.priv_set);
3582                         return NT_STATUS_INVALID_INFO_CLASS;
3583         }
3584
3585         if(!add_mapping_entry(&map, TDB_REPLACE)) {
3586                 free_privilege(&map.priv_set);
3587                 return NT_STATUS_NO_SUCH_GROUP;
3588         }
3589
3590         free_privilege(&map.priv_set);
3591
3592         return NT_STATUS_OK;
3593 }
3594
3595 /*********************************************************************
3596  _samr_set_groupinfo
3597  
3598  update a domain group's comment.
3599 *********************************************************************/
3600
3601 NTSTATUS _samr_set_aliasinfo(pipes_struct *p, SAMR_Q_SET_ALIASINFO *q_u, SAMR_R_SET_ALIASINFO *r_u)
3602 {
3603         DOM_SID group_sid;
3604         GROUP_MAP map;
3605         ALIAS_INFO_CTR *ctr;
3606
3607         if (!get_lsa_policy_samr_sid(p, &q_u->alias_pol, &group_sid)) 
3608                 return NT_STATUS_INVALID_HANDLE;
3609
3610         if (!get_local_group_from_sid(group_sid, &map, MAPPING_WITH_PRIV))
3611                 return NT_STATUS_NO_SUCH_GROUP;
3612         
3613         ctr=&q_u->ctr;
3614
3615         switch (ctr->switch_value1) {
3616                 case 3:
3617                         unistr2_to_ascii(map.comment, &(ctr->alias.info3.uni_acct_desc), sizeof(map.comment)-1);
3618                         break;
3619                 default:
3620                         free_privilege(&map.priv_set);
3621                         return NT_STATUS_INVALID_INFO_CLASS;
3622         }
3623
3624         if(!add_mapping_entry(&map, TDB_REPLACE)) {
3625                 free_privilege(&map.priv_set);
3626                 return NT_STATUS_NO_SUCH_GROUP;
3627         }
3628
3629         free_privilege(&map.priv_set);
3630
3631         return NT_STATUS_OK;
3632 }
3633
3634 /*********************************************************************
3635  _samr_get_dom_pwinfo
3636 *********************************************************************/
3637
3638 NTSTATUS _samr_get_dom_pwinfo(pipes_struct *p, SAMR_Q_GET_DOM_PWINFO *q_u, SAMR_R_GET_DOM_PWINFO *r_u)
3639 {
3640         /* Perform access check.  Since this rpc does not require a
3641            policy handle it will not be caught by the access checks on
3642            SAMR_CONNECT or SAMR_CONNECT_ANON. */
3643
3644         if (!pipe_access_check(p)) {
3645                 DEBUG(3, ("access denied to samr_get_dom_pwinfo\n"));
3646                 r_u->status = NT_STATUS_ACCESS_DENIED;
3647                 return r_u->status;
3648         }
3649
3650         /* Actually, returning zeros here works quite well :-). */
3651
3652         return NT_STATUS_OK;
3653 }
3654
3655 /*********************************************************************
3656  _samr_open_group
3657 *********************************************************************/
3658
3659 NTSTATUS _samr_open_group(pipes_struct *p, SAMR_Q_OPEN_GROUP *q_u, SAMR_R_OPEN_GROUP *r_u)
3660 {
3661         DOM_SID sid;
3662         DOM_SID info_sid;
3663         GROUP_MAP map;
3664         struct samr_info *info;
3665         fstring sid_string;
3666
3667         if (!get_lsa_policy_samr_sid(p, &q_u->domain_pol, &sid)) 
3668                 return NT_STATUS_INVALID_HANDLE;
3669
3670         /* this should not be hard-coded like this */
3671         if (!sid_equal(&sid, get_global_sam_sid()))
3672                 return NT_STATUS_ACCESS_DENIED;
3673
3674         sid_copy(&info_sid, get_global_sam_sid());
3675         sid_append_rid(&info_sid, q_u->rid_group);
3676         sid_to_string(sid_string, &info_sid);
3677
3678         if ((info = get_samr_info_by_sid(&info_sid)) == NULL)
3679                 return NT_STATUS_NO_MEMORY;
3680
3681         DEBUG(10, ("_samr_open_group:Opening SID: %s\n", sid_string));
3682
3683         /* check if that group really exists */
3684         if (!get_domain_group_from_sid(info->sid, &map, MAPPING_WITHOUT_PRIV))
3685                 return NT_STATUS_NO_SUCH_GROUP;
3686
3687         /* get a (unique) handle.  open a policy on it. */
3688         if (!create_policy_hnd(p, &r_u->pol, free_samr_info, (void *)info))
3689                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3690
3691         return NT_STATUS_OK;
3692 }
3693
3694 /*********************************************************************
3695  _samr_unknown_2d
3696 *********************************************************************/
3697
3698 NTSTATUS _samr_unknown_2d(pipes_struct *p, SAMR_Q_UNKNOWN_2D *q_u, SAMR_R_UNKNOWN_2D *r_u)
3699 {
3700         DEBUG(0,("_samr_unknown_2d: Not yet implemented.\n"));
3701         return NT_STATUS_NOT_IMPLEMENTED;
3702 }
3703
3704 /*******************************************************************
3705  _samr_unknown_2e
3706  ********************************************************************/
3707
3708 NTSTATUS _samr_unknown_2e(pipes_struct *p, SAMR_Q_UNKNOWN_2E *q_u, SAMR_R_UNKNOWN_2E *r_u)
3709 {
3710         struct samr_info *info = NULL;
3711         SAM_UNK_CTR *ctr;
3712         uint32 min_pass_len,pass_hist,flag;
3713         time_t u_expire, u_min_age;
3714         NTTIME nt_expire, nt_min_age;
3715
3716         time_t u_lock_duration, u_reset_time;
3717         NTTIME nt_lock_duration, nt_reset_time;
3718         uint32 lockout;
3719         
3720         time_t u_logout;
3721         NTTIME nt_logout;
3722
3723         uint32 num_users=0, num_groups=0, num_aliases=0;
3724
3725         if ((ctr = (SAM_UNK_CTR *)talloc_zero(p->mem_ctx, sizeof(SAM_UNK_CTR))) == NULL)
3726                 return NT_STATUS_NO_MEMORY;
3727
3728         ZERO_STRUCTP(ctr);
3729
3730         r_u->status = NT_STATUS_OK;
3731
3732         DEBUG(5,("_samr_unknown_2e: %d\n", __LINE__));
3733
3734         /* find the policy handle.  open a policy on it. */
3735         if (!find_policy_by_hnd(p, &q_u->domain_pol, (void **)&info))
3736                 return NT_STATUS_INVALID_HANDLE;
3737
3738         switch (q_u->switch_value) {
3739                 case 0x01:
3740                         account_policy_get(AP_MIN_PASSWORD_LEN, &min_pass_len);
3741                         account_policy_get(AP_PASSWORD_HISTORY, &pass_hist);
3742                         account_policy_get(AP_USER_MUST_LOGON_TO_CHG_PASS, &flag);
3743                         account_policy_get(AP_MAX_PASSWORD_AGE, (int *)&u_expire);
3744                         account_policy_get(AP_MIN_PASSWORD_AGE, (int *)&u_min_age);
3745
3746                         unix_to_nt_time_abs(&nt_expire, u_expire);
3747                         unix_to_nt_time_abs(&nt_min_age, u_min_age);
3748
3749                         init_unk_info1(&ctr->info.inf1, (uint16)min_pass_len, (uint16)pass_hist, 
3750                                        flag, nt_expire, nt_min_age);
3751                         break;
3752                 case 0x02:
3753                         become_root();          
3754                         r_u->status=load_sampwd_entries(info, ACB_NORMAL);
3755                         unbecome_root();
3756                         if (!NT_STATUS_IS_OK(r_u->status)) {
3757                                 DEBUG(5, ("_samr_query_dispinfo: load_sampwd_entries failed\n"));
3758                                 return r_u->status;
3759                         }
3760                         num_users=info->disp_info.num_user_account;
3761                         free_samr_db(info);
3762                         
3763                         r_u->status=load_group_domain_entries(info, get_global_sam_sid());
3764                         if (NT_STATUS_IS_ERR(r_u->status)) {
3765                                 DEBUG(5, ("_samr_query_dispinfo: load_group_domain_entries failed\n"));
3766                                 return r_u->status;
3767                         }
3768                         num_groups=info->disp_info.num_group_account;
3769                         free_samr_db(info);
3770
3771                         /* The time call below is to get a sequence number for the sam. FIXME !!! JRA. */
3772                         init_unk_info2(&ctr->info.inf2, global_myworkgroup, global_myname, (uint32) time(NULL), 
3773                                        num_users, num_groups, num_aliases);
3774                         break;
3775                 case 0x03:
3776                         account_policy_get(AP_TIME_TO_LOGOUT, (int *)&u_logout);
3777                         unix_to_nt_time_abs(&nt_logout, u_logout);
3778                         
3779                         init_unk_info3(&ctr->info.inf3, nt_logout);
3780                         break;
3781                 case 0x05:
3782                         init_unk_info5(&ctr->info.inf5, global_myname);
3783                         break;
3784                 case 0x06:
3785                         init_unk_info6(&ctr->info.inf6);
3786                         break;
3787                 case 0x07:
3788                         init_unk_info7(&ctr->info.inf7);
3789                         break;
3790                 case 0x0c:
3791                         account_policy_get(AP_LOCK_ACCOUNT_DURATION, (int *)&u_lock_duration);
3792                         account_policy_get(AP_RESET_COUNT_TIME, (int *)&u_reset_time);
3793                         account_policy_get(AP_BAD_ATTEMPT_LOCKOUT, &lockout);
3794         
3795                         unix_to_nt_time_abs(&nt_lock_duration, u_lock_duration);
3796                         unix_to_nt_time_abs(&nt_reset_time, u_reset_time);
3797         
3798                         init_unk_info12(&ctr->info.inf12, nt_lock_duration, nt_reset_time, (uint16)lockout);
3799                         break;
3800                 default:
3801                         return NT_STATUS_INVALID_INFO_CLASS;
3802         }
3803
3804         init_samr_r_samr_unknown_2e(r_u, q_u->switch_value, ctr, NT_STATUS_OK);
3805
3806         DEBUG(5,("_samr_unknown_2e: %d\n", __LINE__));
3807
3808         return r_u->status;