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