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