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