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