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