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