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