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