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