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