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