r801: Fix from "Jianliang Lu" <j.lu@tiesse.com> to return correct group
[amitay/samba.git] / source3 / rpc_server / srv_lsa_nt.c
1 /* 
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *  Copyright (C) Andrew Tridgell              1992-1997,
5  *  Copyright (C) Luke Kenneth Casson Leighton 1996-1997,
6  *  Copyright (C) Paul Ashton                       1997,
7  *  Copyright (C) Jeremy Allison                    2001,
8  *  Copyright (C) Rafal Szczesniak                  2002,
9  *  Copyright (C) Jim McDonough <jmcd@us.ibm.com>   2002,
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 /* This is the implementation of the lsa server code. */
27
28 #include "includes.h"
29
30 #undef DBGC_CLASS
31 #define DBGC_CLASS DBGC_RPC_SRV
32
33 extern PRIVS privs[];
34
35 struct lsa_info {
36         DOM_SID sid;
37         uint32 access;
38 };
39
40 struct generic_mapping lsa_generic_mapping = {
41         POLICY_READ,
42         POLICY_WRITE,
43         POLICY_EXECUTE,
44         POLICY_ALL_ACCESS
45 };
46
47 /*******************************************************************
48  Function to free the per handle data.
49  ********************************************************************/
50
51 static void free_lsa_info(void *ptr)
52 {
53         struct lsa_info *lsa = (struct lsa_info *)ptr;
54
55         SAFE_FREE(lsa);
56 }
57
58 /***************************************************************************
59 Init dom_query
60  ***************************************************************************/
61
62 static void init_dom_query(DOM_QUERY *d_q, const char *dom_name, DOM_SID *dom_sid)
63 {
64         d_q->buffer_dom_name = (dom_name != NULL) ? 1 : 0; /* domain buffer pointer */
65         d_q->buffer_dom_sid = (dom_sid != NULL) ? 1 : 0;  /* domain sid pointer */
66
67         /* this string is supposed to be non-null terminated. */
68         /* But the maxlen in this UNISTR2 must include the terminating null. */
69         init_unistr2(&d_q->uni_domain_name, dom_name, UNI_BROKEN_NON_NULL);
70
71         /*
72          * I'm not sure why this really odd combination of length
73          * values works, but it does appear to. I need to look at
74          * this *much* more closely - but at the moment leave alone
75          * until it's understood. This allows a W2k client to join
76          * a domain with both odd and even length names... JRA.
77          */
78
79         /*
80          * IMPORTANT NOTE !!!!
81          * The two fields below probably are reversed in meaning, ie.
82          * the first field is probably the str_len, the second the max
83          * len. Both are measured in bytes anyway.
84          */
85
86         d_q->uni_dom_str_len = d_q->uni_domain_name.uni_max_len * 2;
87         d_q->uni_dom_max_len = d_q->uni_domain_name.uni_str_len * 2;
88
89         if (dom_sid != NULL)
90                 init_dom_sid2(&d_q->dom_sid, dom_sid);
91 }
92
93 /***************************************************************************
94  init_dom_ref - adds a domain if it's not already in, returns the index.
95 ***************************************************************************/
96
97 static int init_dom_ref(DOM_R_REF *ref, char *dom_name, DOM_SID *dom_sid)
98 {
99         int num = 0;
100
101         if (dom_name != NULL) {
102                 for (num = 0; num < ref->num_ref_doms_1; num++) {
103                         fstring domname;
104                         rpcstr_pull(domname, &ref->ref_dom[num].uni_dom_name, sizeof(domname), -1, 0);
105                         if (strequal(domname, dom_name))
106                                 return num;
107                 }
108         } else {
109                 num = ref->num_ref_doms_1;
110         }
111
112         if (num >= MAX_REF_DOMAINS) {
113                 /* index not found, already at maximum domain limit */
114                 return -1;
115         }
116
117         ref->num_ref_doms_1 = num+1;
118         ref->ptr_ref_dom  = 1;
119         ref->max_entries = MAX_REF_DOMAINS;
120         ref->num_ref_doms_2 = num+1;
121
122         ref->hdr_ref_dom[num].ptr_dom_sid = dom_sid != NULL ? 1 : 0;
123
124         init_unistr2(&ref->ref_dom[num].uni_dom_name, dom_name, UNI_FLAGS_NONE);
125         init_uni_hdr(&ref->hdr_ref_dom[num].hdr_dom_name, &ref->ref_dom[num].uni_dom_name);
126
127         init_dom_sid2(&ref->ref_dom[num].ref_dom, dom_sid );
128
129         return num;
130 }
131
132 /***************************************************************************
133  init_lsa_rid2s
134  ***************************************************************************/
135
136 static void init_lsa_rid2s(DOM_R_REF *ref, DOM_RID2 *rid2,
137                                 int num_entries, UNISTR2 *name,
138                                 uint32 *mapped_count, BOOL endian)
139 {
140         int i;
141         int total = 0;
142         *mapped_count = 0;
143
144         SMB_ASSERT(num_entries <= MAX_LOOKUP_SIDS);
145
146         become_root(); /* lookup_name can require root privs */
147
148         for (i = 0; i < num_entries; i++) {
149                 BOOL status = False;
150                 DOM_SID sid;
151                 uint32 rid = 0xffffffff;
152                 int dom_idx = -1;
153                 pstring full_name;
154                 fstring dom_name, user;
155                 enum SID_NAME_USE name_type = SID_NAME_UNKNOWN;
156
157                 /* Split name into domain and user component */
158
159                 unistr2_to_ascii(full_name, &name[i], sizeof(full_name));
160                 split_domain_name(full_name, dom_name, user);
161
162                 /* Lookup name */
163
164                 DEBUG(5, ("init_lsa_rid2s: looking up name %s\n", full_name));
165
166                 status = lookup_name(dom_name, user, &sid, &name_type);
167
168                 if((name_type == SID_NAME_UNKNOWN) && (lp_server_role() == ROLE_DOMAIN_MEMBER)  && (strncmp(dom_name, full_name, strlen(dom_name)) != 0)) {
169                         DEBUG(5, ("init_lsa_rid2s: domain name not provided and local account not found, using member domain\n"));
170                         fstrcpy(dom_name, lp_workgroup());
171                         status = lookup_name(dom_name, user, &sid, &name_type);
172                 }
173
174 #if 0 /* This is not true. */
175                 if (name_type == SID_NAME_WKN_GRP) {
176                         /* BUILTIN aliases are still aliases :-) */
177                         name_type = SID_NAME_ALIAS;
178                 }
179 #endif
180
181                 DEBUG(5, ("init_lsa_rid2s: %s\n", status ? "found" : 
182                           "not found"));
183
184                 if (status && name_type != SID_NAME_UNKNOWN) {
185                         sid_split_rid(&sid, &rid);
186                         dom_idx = init_dom_ref(ref, dom_name, &sid);
187                         (*mapped_count)++;
188                 } else {
189                         dom_idx = -1;
190                         rid = 0;
191                         name_type = SID_NAME_UNKNOWN;
192                 }
193
194                 init_dom_rid2(&rid2[total], rid, name_type, dom_idx);
195                 total++;
196         }
197
198         unbecome_root();
199 }
200
201 /***************************************************************************
202  init_reply_lookup_names
203  ***************************************************************************/
204
205 static void init_reply_lookup_names(LSA_R_LOOKUP_NAMES *r_l,
206                 DOM_R_REF *ref, uint32 num_entries,
207                 DOM_RID2 *rid2, uint32 mapped_count)
208 {
209         r_l->ptr_dom_ref  = 1;
210         r_l->dom_ref      = ref;
211
212         r_l->num_entries  = num_entries;
213         r_l->ptr_entries  = 1;
214         r_l->num_entries2 = num_entries;
215         r_l->dom_rid      = rid2;
216
217         r_l->mapped_count = mapped_count;
218 }
219
220 /***************************************************************************
221  Init lsa_trans_names.
222  ***************************************************************************/
223
224 static void init_lsa_trans_names(TALLOC_CTX *ctx, DOM_R_REF *ref, LSA_TRANS_NAME_ENUM *trn,
225                                  int num_entries, DOM_SID2 *sid,
226                                  uint32 *mapped_count)
227 {
228         int i;
229         int total = 0;
230         *mapped_count = 0;
231
232         /* Allocate memory for list of names */
233
234         if (num_entries > 0) {
235                 if (!(trn->name = (LSA_TRANS_NAME *)talloc(ctx, sizeof(LSA_TRANS_NAME) *
236                                                           num_entries))) {
237                         DEBUG(0, ("init_lsa_trans_names(): out of memory\n"));
238                         return;
239                 }
240
241                 if (!(trn->uni_name = (UNISTR2 *)talloc(ctx, sizeof(UNISTR2) * 
242                                                         num_entries))) {
243                         DEBUG(0, ("init_lsa_trans_names(): out of memory\n"));
244                         return;
245                 }
246         }
247
248         become_root(); /* Need root to get to passdb to for local sids */
249
250         for (i = 0; i < num_entries; i++) {
251                 BOOL status = False;
252                 DOM_SID find_sid = sid[i].sid;
253                 uint32 rid = 0xffffffff;
254                 int dom_idx = -1;
255                 fstring name, dom_name;
256                 enum SID_NAME_USE sid_name_use = (enum SID_NAME_USE)0;
257
258                 sid_to_string(name, &find_sid);
259                 DEBUG(5, ("init_lsa_trans_names: looking up sid %s\n", name));
260
261                 /* Lookup sid from winbindd */
262
263                 status = lookup_sid(&find_sid, dom_name, name, &sid_name_use);
264
265                 DEBUG(5, ("init_lsa_trans_names: %s\n", status ? "found" : 
266                           "not found"));
267
268                 if (!status) {
269                         sid_name_use = SID_NAME_UNKNOWN;
270                         memset(dom_name, '\0', sizeof(dom_name));
271                         sid_to_string(name, &find_sid);
272                         dom_idx = -1;
273
274                         DEBUG(10,("init_lsa_trans_names: added unknown user '%s' to "
275                                   "referenced list.\n", name ));
276                 } else {
277                         (*mapped_count)++;
278                         /* Store domain sid in ref array */
279                         if (find_sid.num_auths == 5) {
280                                 sid_split_rid(&find_sid, &rid);
281                         }
282                         dom_idx = init_dom_ref(ref, dom_name, &find_sid);
283
284                         DEBUG(10,("init_lsa_trans_names: added user '%s\\%s' to "
285                                   "referenced list.\n", dom_name, name ));
286
287                 }
288
289                 init_lsa_trans_name(&trn->name[total], &trn->uni_name[total],
290                                         sid_name_use, name, dom_idx);
291                 total++;
292         }
293
294         unbecome_root();
295
296         trn->num_entries = total;
297         trn->ptr_trans_names = 1;
298         trn->num_entries2 = total;
299 }
300
301 /***************************************************************************
302  Init_reply_lookup_sids.
303  ***************************************************************************/
304
305 static void init_reply_lookup_sids(LSA_R_LOOKUP_SIDS *r_l,
306                 DOM_R_REF *ref, LSA_TRANS_NAME_ENUM *names,
307                 uint32 mapped_count)
308 {
309         r_l->ptr_dom_ref  = 1;
310         r_l->dom_ref      = ref;
311         r_l->names        = names;
312         r_l->mapped_count = mapped_count;
313 }
314
315 static NTSTATUS lsa_get_generic_sd(TALLOC_CTX *mem_ctx, SEC_DESC **sd, size_t *sd_size)
316 {
317         extern DOM_SID global_sid_World;
318         extern DOM_SID global_sid_Builtin;
319         DOM_SID local_adm_sid;
320         DOM_SID adm_sid;
321
322         SEC_ACE ace[3];
323         SEC_ACCESS mask;
324
325         SEC_ACL *psa = NULL;
326
327         init_sec_access(&mask, POLICY_EXECUTE);
328         init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
329
330         sid_copy(&adm_sid, get_global_sam_sid());
331         sid_append_rid(&adm_sid, DOMAIN_GROUP_RID_ADMINS);
332         init_sec_access(&mask, POLICY_ALL_ACCESS);
333         init_sec_ace(&ace[1], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
334
335         sid_copy(&local_adm_sid, &global_sid_Builtin);
336         sid_append_rid(&local_adm_sid, BUILTIN_ALIAS_RID_ADMINS);
337         init_sec_access(&mask, POLICY_ALL_ACCESS);
338         init_sec_ace(&ace[2], &local_adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
339
340         if((psa = make_sec_acl(mem_ctx, NT4_ACL_REVISION, 3, ace)) == NULL)
341                 return NT_STATUS_NO_MEMORY;
342
343         if((*sd = make_sec_desc(mem_ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, &adm_sid, NULL, NULL, psa, sd_size)) == NULL)
344                 return NT_STATUS_NO_MEMORY;
345
346         return NT_STATUS_OK;
347 }
348
349 /***************************************************************************
350  Init_dns_dom_info.
351 ***************************************************************************/
352
353 static void init_dns_dom_info(LSA_DNS_DOM_INFO *r_l, const char *nb_name,
354                               const char *dns_name, const char *forest_name,
355                               struct uuid *dom_guid, DOM_SID *dom_sid)
356 {
357         if (nb_name && *nb_name) {
358                 init_unistr2(&r_l->uni_nb_dom_name, nb_name, UNI_FLAGS_NONE);
359                 init_uni_hdr(&r_l->hdr_nb_dom_name, &r_l->uni_nb_dom_name);
360                 r_l->hdr_nb_dom_name.uni_max_len += 2;
361                 r_l->uni_nb_dom_name.uni_max_len += 1;
362         }
363         
364         if (dns_name && *dns_name) {
365                 init_unistr2(&r_l->uni_dns_dom_name, dns_name, UNI_FLAGS_NONE);
366                 init_uni_hdr(&r_l->hdr_dns_dom_name, &r_l->uni_dns_dom_name);
367                 r_l->hdr_dns_dom_name.uni_max_len += 2;
368                 r_l->uni_dns_dom_name.uni_max_len += 1;
369         }
370
371         if (forest_name && *forest_name) {
372                 init_unistr2(&r_l->uni_forest_name, forest_name, UNI_FLAGS_NONE);
373                 init_uni_hdr(&r_l->hdr_forest_name, &r_l->uni_forest_name);
374                 r_l->hdr_forest_name.uni_max_len += 2;
375                 r_l->uni_forest_name.uni_max_len += 1;
376         }
377
378         /* how do we init the guid ? probably should write an init fn */
379         if (dom_guid) {
380                 memcpy(&r_l->dom_guid, dom_guid, sizeof(struct uuid));
381         }
382         
383         if (dom_sid) {
384                 r_l->ptr_dom_sid = 1;
385                 init_dom_sid2(&r_l->dom_sid, dom_sid);
386         }
387 }
388
389 /***************************************************************************
390  _lsa_open_policy2.
391  ***************************************************************************/
392
393 NTSTATUS _lsa_open_policy2(pipes_struct *p, LSA_Q_OPEN_POL2 *q_u, LSA_R_OPEN_POL2 *r_u)
394 {
395         struct lsa_info *info;
396         SEC_DESC *psd = NULL;
397         size_t sd_size;
398         uint32 des_access=q_u->des_access;
399         uint32 acc_granted;
400         NTSTATUS status;
401
402
403         /* map the generic bits to the lsa policy ones */
404         se_map_generic(&des_access, &lsa_generic_mapping);
405
406         /* get the generic lsa policy SD until we store it */
407         lsa_get_generic_sd(p->mem_ctx, &psd, &sd_size);
408
409         if(!se_access_check(psd, p->pipe_user.nt_user_token, des_access, &acc_granted, &status)) {
410                 if (geteuid() != 0) {
411                         return status;
412                 }
413                 DEBUG(4,("ACCESS should be DENIED (granted: %#010x;  required: %#010x)\n",
414                          acc_granted, des_access));
415                 DEBUGADD(4,("but overwritten by euid == 0\n"));
416                 acc_granted = des_access;
417         }
418
419
420         /* associate the domain SID with the (unique) handle. */
421         if ((info = (struct lsa_info *)malloc(sizeof(struct lsa_info))) == NULL)
422                 return NT_STATUS_NO_MEMORY;
423
424         ZERO_STRUCTP(info);
425         sid_copy(&info->sid,get_global_sam_sid());
426         info->access = acc_granted;
427
428         /* set up the LSA QUERY INFO response */
429         if (!create_policy_hnd(p, &r_u->pol, free_lsa_info, (void *)info))
430                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
431
432         return NT_STATUS_OK;
433 }
434
435 /***************************************************************************
436  _lsa_open_policy
437  ***************************************************************************/
438
439 NTSTATUS _lsa_open_policy(pipes_struct *p, LSA_Q_OPEN_POL *q_u, LSA_R_OPEN_POL *r_u)
440 {
441         struct lsa_info *info;
442         SEC_DESC *psd = NULL;
443         size_t sd_size;
444         uint32 des_access=q_u->des_access;
445         uint32 acc_granted;
446         NTSTATUS status;
447
448
449         /* map the generic bits to the lsa policy ones */
450         se_map_generic(&des_access, &lsa_generic_mapping);
451
452         /* get the generic lsa policy SD until we store it */
453         lsa_get_generic_sd(p->mem_ctx, &psd, &sd_size);
454
455         if(!se_access_check(psd, p->pipe_user.nt_user_token, des_access, &acc_granted, &status)) {
456                 if (geteuid() != 0) {
457                         return status;
458                 }
459                 DEBUG(4,("ACCESS should be DENIED (granted: %#010x;  required: %#010x)\n",
460                          acc_granted, des_access));
461                 DEBUGADD(4,("but overwritten by euid == 0\n"));
462                 acc_granted = des_access;
463         }
464
465         /* associate the domain SID with the (unique) handle. */
466         if ((info = (struct lsa_info *)malloc(sizeof(struct lsa_info))) == NULL)
467                 return NT_STATUS_NO_MEMORY;
468
469         ZERO_STRUCTP(info);
470         sid_copy(&info->sid,get_global_sam_sid());
471         info->access = acc_granted;
472
473         /* set up the LSA QUERY INFO response */
474         if (!create_policy_hnd(p, &r_u->pol, free_lsa_info, (void *)info))
475                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
476
477         return NT_STATUS_OK;
478 }
479
480 /***************************************************************************
481  _lsa_enum_trust_dom - this needs fixing to do more than return NULL ! JRA.
482  ufff, done :)  mimir
483  ***************************************************************************/
484
485 NTSTATUS _lsa_enum_trust_dom(pipes_struct *p, LSA_Q_ENUM_TRUST_DOM *q_u, LSA_R_ENUM_TRUST_DOM *r_u)
486 {
487         struct lsa_info *info;
488         uint32 enum_context = q_u->enum_context;
489
490         /*
491          * preferred length is set to 5 as a "our" preferred length
492          * nt sets this parameter to 2
493          * update (20.08.2002): it's not preferred length, but preferred size!
494          * it needs further investigation how to optimally choose this value
495          */
496         uint32 max_num_domains = q_u->preferred_len < 5 ? q_u->preferred_len : 10;
497         TRUSTDOM **trust_doms;
498         uint32 num_domains;
499         NTSTATUS nt_status;
500
501         if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info))
502                 return NT_STATUS_INVALID_HANDLE;
503
504         /* check if the user have enough rights */
505         if (!(info->access & POLICY_VIEW_LOCAL_INFORMATION))
506                 return NT_STATUS_ACCESS_DENIED;
507
508         nt_status = secrets_get_trusted_domains(p->mem_ctx, (int *)&enum_context, max_num_domains, (int *)&num_domains, &trust_doms);
509
510         if (!NT_STATUS_IS_OK(nt_status) &&
511             !NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES) &&
512             !NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_MORE_ENTRIES)) {
513                 return nt_status;
514         } else {
515                 r_u->status = nt_status;
516         }
517
518         /* set up the lsa_enum_trust_dom response */
519         init_r_enum_trust_dom(p->mem_ctx, r_u, enum_context, max_num_domains, num_domains, trust_doms);
520
521         return r_u->status;
522 }
523
524 /***************************************************************************
525  _lsa_query_info. See the POLICY_INFOMATION_CLASS docs at msdn.
526  ***************************************************************************/
527
528 NTSTATUS _lsa_query_info(pipes_struct *p, LSA_Q_QUERY_INFO *q_u, LSA_R_QUERY_INFO *r_u)
529 {
530         struct lsa_info *handle;
531         LSA_INFO_UNION *info = &r_u->dom;
532         DOM_SID domain_sid;
533         const char *name;
534         DOM_SID *sid = NULL;
535
536         r_u->status = NT_STATUS_OK;
537
538         if (!find_policy_by_hnd(p, &q_u->pol, (void **)&handle))
539                 return NT_STATUS_INVALID_HANDLE;
540
541         switch (q_u->info_class) {
542         case 0x02:
543                 {
544                 unsigned int i;
545                 /* check if the user have enough rights */
546                 if (!(handle->access & POLICY_VIEW_AUDIT_INFORMATION))
547                         return NT_STATUS_ACCESS_DENIED;
548
549                 /* fake info: We audit everything. ;) */
550                 info->id2.auditing_enabled = 1;
551                 info->id2.count1 = 7;
552                 info->id2.count2 = 7;
553                 if ((info->id2.auditsettings = (uint32 *)talloc(p->mem_ctx,7*sizeof(uint32))) == NULL)
554                         return NT_STATUS_NO_MEMORY;
555                 for (i = 0; i < 7; i++)
556                         info->id2.auditsettings[i] = 3;
557                 break;
558                 }
559         case 0x03:
560                 /* check if the user have enough rights */
561                 if (!(handle->access & POLICY_VIEW_LOCAL_INFORMATION))
562                         return NT_STATUS_ACCESS_DENIED;
563
564                 /* Request PolicyPrimaryDomainInformation. */
565                 switch (lp_server_role()) {
566                         case ROLE_DOMAIN_PDC:
567                         case ROLE_DOMAIN_BDC:
568                                 name = get_global_sam_name();
569                                 sid = get_global_sam_sid();
570                                 break;
571                         case ROLE_DOMAIN_MEMBER:
572                                 name = lp_workgroup();
573                                 /* We need to return the Domain SID here. */
574                                 if (secrets_fetch_domain_sid(lp_workgroup(), &domain_sid))
575                                         sid = &domain_sid;
576                                 else
577                                         return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
578                                 break;
579                         case ROLE_STANDALONE:
580                                 name = lp_workgroup();
581                                 sid = NULL;
582                                 break;
583                         default:
584                                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
585                 }
586                 init_dom_query(&r_u->dom.id3, name, sid);
587                 break;
588         case 0x05:
589                 /* check if the user have enough rights */
590                 if (!(handle->access & POLICY_VIEW_LOCAL_INFORMATION))
591                         return NT_STATUS_ACCESS_DENIED;
592
593                 /* Request PolicyAccountDomainInformation. */
594                 name = get_global_sam_name();
595                 sid = get_global_sam_sid();
596                 init_dom_query(&r_u->dom.id5, name, sid);
597                 break;
598         case 0x06:
599                 /* check if the user have enough rights */
600                 if (!(handle->access & POLICY_VIEW_LOCAL_INFORMATION))
601                         return NT_STATUS_ACCESS_DENIED;
602
603                 switch (lp_server_role()) {
604                         case ROLE_DOMAIN_BDC:
605                                 /*
606                                  * only a BDC is a backup controller
607                                  * of the domain, it controls.
608                                  */
609                                 info->id6.server_role = 2;
610                                 break;
611                         default:
612                                 /*
613                                  * any other role is a primary
614                                  * of the domain, it controls.
615                                  */
616                                 info->id6.server_role = 3;
617                                 break; 
618                 }
619                 break;
620         default:
621                 DEBUG(0,("_lsa_query_info: unknown info level in Lsa Query: %d\n", q_u->info_class));
622                 r_u->status = NT_STATUS_INVALID_INFO_CLASS;
623                 break;
624         }
625
626         if (NT_STATUS_IS_OK(r_u->status)) {
627                 r_u->undoc_buffer = 0x22000000; /* bizarre */
628                 r_u->info_class = q_u->info_class;
629         }
630
631         return r_u->status;
632 }
633
634 /***************************************************************************
635  _lsa_lookup_sids
636  ***************************************************************************/
637
638 NTSTATUS _lsa_lookup_sids(pipes_struct *p, LSA_Q_LOOKUP_SIDS *q_u, LSA_R_LOOKUP_SIDS *r_u)
639 {
640         struct lsa_info *handle;
641         DOM_SID2 *sid = q_u->sids.sid;
642         int num_entries = q_u->sids.num_entries;
643         DOM_R_REF *ref = NULL;
644         LSA_TRANS_NAME_ENUM *names = NULL;
645         uint32 mapped_count = 0;
646
647         if (num_entries >  MAX_LOOKUP_SIDS) {
648                 num_entries = MAX_LOOKUP_SIDS;
649                 DEBUG(5,("_lsa_lookup_sids: truncating SID lookup list to %d\n", num_entries));
650         }
651
652         ref = (DOM_R_REF *)talloc_zero(p->mem_ctx, sizeof(DOM_R_REF));
653         names = (LSA_TRANS_NAME_ENUM *)talloc_zero(p->mem_ctx, sizeof(LSA_TRANS_NAME_ENUM));
654
655         if (!find_policy_by_hnd(p, &q_u->pol, (void **)&handle)) {
656                 r_u->status = NT_STATUS_INVALID_HANDLE;
657                 goto done;
658         }
659
660         /* check if the user have enough rights */
661         if (!(handle->access & POLICY_LOOKUP_NAMES)) {
662                 r_u->status = NT_STATUS_ACCESS_DENIED;
663                 goto done;
664         }
665         if (!ref || !names)
666                 return NT_STATUS_NO_MEMORY;
667
668 done:
669
670         /* set up the LSA Lookup SIDs response */
671         init_lsa_trans_names(p->mem_ctx, ref, names, num_entries, sid, &mapped_count);
672         if (mapped_count == 0)
673                 r_u->status = NT_STATUS_NONE_MAPPED;
674         else if (mapped_count != num_entries)
675                 r_u->status = STATUS_SOME_UNMAPPED;
676         else
677                 r_u->status = NT_STATUS_OK;
678         init_reply_lookup_sids(r_u, ref, names, mapped_count);
679
680         return r_u->status;
681 }
682
683 /***************************************************************************
684 lsa_reply_lookup_names
685  ***************************************************************************/
686
687 NTSTATUS _lsa_lookup_names(pipes_struct *p,LSA_Q_LOOKUP_NAMES *q_u, LSA_R_LOOKUP_NAMES *r_u)
688 {
689         struct lsa_info *handle;
690         UNISTR2 *names = q_u->uni_name;
691         int num_entries = q_u->num_entries;
692         DOM_R_REF *ref;
693         DOM_RID2 *rids;
694         uint32 mapped_count = 0;
695
696         if (num_entries >  MAX_LOOKUP_SIDS) {
697                 num_entries = MAX_LOOKUP_SIDS;
698                 DEBUG(5,("_lsa_lookup_names: truncating name lookup list to %d\n", num_entries));
699         }
700                 
701         ref = (DOM_R_REF *)talloc_zero(p->mem_ctx, sizeof(DOM_R_REF));
702         rids = (DOM_RID2 *)talloc_zero(p->mem_ctx, sizeof(DOM_RID2)*num_entries);
703
704         if (!find_policy_by_hnd(p, &q_u->pol, (void **)&handle)) {
705                 r_u->status = NT_STATUS_INVALID_HANDLE;
706                 goto done;
707         }
708
709         /* check if the user have enough rights */
710         if (!(handle->access & POLICY_LOOKUP_NAMES)) {
711                 r_u->status = NT_STATUS_ACCESS_DENIED;
712                 goto done;
713         }
714
715         if (!ref || !rids)
716                 return NT_STATUS_NO_MEMORY;
717
718 done:
719
720         /* set up the LSA Lookup RIDs response */
721         init_lsa_rid2s(ref, rids, num_entries, names, &mapped_count, p->endian);
722         if (mapped_count == 0)
723                 r_u->status = NT_STATUS_NONE_MAPPED;
724         else if (mapped_count != num_entries)
725                 r_u->status = STATUS_SOME_UNMAPPED;
726         else
727                 r_u->status = NT_STATUS_OK;
728         init_reply_lookup_names(r_u, ref, num_entries, rids, mapped_count);
729
730         return r_u->status;
731 }
732
733 /***************************************************************************
734  _lsa_close. Also weird - needs to check if lsa handle is correct. JRA.
735  ***************************************************************************/
736
737 NTSTATUS _lsa_close(pipes_struct *p, LSA_Q_CLOSE *q_u, LSA_R_CLOSE *r_u)
738 {
739         if (!find_policy_by_hnd(p, &q_u->pol, NULL))
740                 return NT_STATUS_INVALID_HANDLE;
741
742         close_policy_hnd(p, &q_u->pol);
743         return NT_STATUS_OK;
744 }
745
746 /***************************************************************************
747   "No more secrets Marty...." :-).
748  ***************************************************************************/
749
750 NTSTATUS _lsa_open_secret(pipes_struct *p, LSA_Q_OPEN_SECRET *q_u, LSA_R_OPEN_SECRET *r_u)
751 {
752         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
753 }
754
755 /***************************************************************************
756 _lsa_enum_privs.
757  ***************************************************************************/
758
759 NTSTATUS _lsa_enum_privs(pipes_struct *p, LSA_Q_ENUM_PRIVS *q_u, LSA_R_ENUM_PRIVS *r_u)
760 {
761         struct lsa_info *handle;
762         uint32 i;
763
764         uint32 enum_context=q_u->enum_context;
765         LSA_PRIV_ENTRY *entry;
766         LSA_PRIV_ENTRY *entries=NULL;
767
768         if (enum_context >= PRIV_ALL_INDEX)
769                 return NT_STATUS_NO_MORE_ENTRIES;
770
771         entries = (LSA_PRIV_ENTRY *)talloc_zero(p->mem_ctx, sizeof(LSA_PRIV_ENTRY) * (PRIV_ALL_INDEX));
772         if (entries==NULL)
773                 return NT_STATUS_NO_MEMORY;
774
775         if (!find_policy_by_hnd(p, &q_u->pol, (void **)&handle))
776                 return NT_STATUS_INVALID_HANDLE;
777
778         /* check if the user have enough rights */
779
780         /*
781          * I don't know if it's the right one. not documented.
782          */
783         if (!(handle->access & POLICY_VIEW_LOCAL_INFORMATION))
784                 return NT_STATUS_ACCESS_DENIED;
785
786         entry = entries;
787         
788         DEBUG(10,("_lsa_enum_privs: enum_context:%d total entries:%d\n", enum_context, PRIV_ALL_INDEX));
789
790         for (i = 0; i < PRIV_ALL_INDEX; i++, entry++) {
791                 if( i<enum_context) {
792                         init_unistr2(&entry->name, NULL, UNI_FLAGS_NONE);
793                         init_uni_hdr(&entry->hdr_name, &entry->name);
794                         entry->luid_low = 0;
795                         entry->luid_high = 0;
796                 } else {
797                         init_unistr2(&entry->name, privs[i+1].priv, UNI_FLAGS_NONE);
798                         init_uni_hdr(&entry->hdr_name, &entry->name);
799                         entry->luid_low = privs[i+1].se_priv;
800                         entry->luid_high = 0;
801                 }
802         }
803
804         enum_context = PRIV_ALL_INDEX;
805         init_lsa_r_enum_privs(r_u, enum_context, PRIV_ALL_INDEX, entries);
806
807         return NT_STATUS_OK;
808 }
809
810 /***************************************************************************
811 _lsa_priv_get_dispname.
812  ***************************************************************************/
813
814 NTSTATUS _lsa_priv_get_dispname(pipes_struct *p, LSA_Q_PRIV_GET_DISPNAME *q_u, LSA_R_PRIV_GET_DISPNAME *r_u)
815 {
816         struct lsa_info *handle;
817         fstring name_asc;
818         int i=1;
819
820         if (!find_policy_by_hnd(p, &q_u->pol, (void **)&handle))
821                 return NT_STATUS_INVALID_HANDLE;
822
823         /* check if the user have enough rights */
824
825         /*
826          * I don't know if it's the right one. not documented.
827          */
828         if (!(handle->access & POLICY_VIEW_LOCAL_INFORMATION))
829                 return NT_STATUS_ACCESS_DENIED;
830
831         unistr2_to_ascii(name_asc, &q_u->name, sizeof(name_asc));
832
833         DEBUG(10,("_lsa_priv_get_dispname: %s", name_asc));
834
835         while (privs[i].se_priv!=SE_PRIV_ALL && strcmp(name_asc, privs[i].priv))
836                 i++;
837         
838         if (privs[i].se_priv!=SE_PRIV_ALL) {
839                 DEBUG(10,(": %s\n", privs[i].description));
840                 init_unistr2(&r_u->desc, privs[i].description, UNI_FLAGS_NONE);
841                 init_uni_hdr(&r_u->hdr_desc, &r_u->desc);
842
843                 r_u->ptr_info=0xdeadbeef;
844                 r_u->lang_id=q_u->lang_id;
845                 return NT_STATUS_OK;
846         } else {
847                 DEBUG(10,("_lsa_priv_get_dispname: doesn't exist\n"));
848                 r_u->ptr_info=0;
849                 return NT_STATUS_NO_SUCH_PRIVILEGE;
850         }
851 }
852
853 /***************************************************************************
854 _lsa_enum_accounts.
855  ***************************************************************************/
856
857 NTSTATUS _lsa_enum_accounts(pipes_struct *p, LSA_Q_ENUM_ACCOUNTS *q_u, LSA_R_ENUM_ACCOUNTS *r_u)
858 {
859         struct lsa_info *handle;
860         GROUP_MAP *map=NULL;
861         int num_entries=0;
862         LSA_SID_ENUM *sids=&r_u->sids;
863         int i=0,j=0;
864         BOOL ret;
865
866         if (!find_policy_by_hnd(p, &q_u->pol, (void **)&handle))
867                 return NT_STATUS_INVALID_HANDLE;
868
869         /* check if the user have enough rights */
870
871         /*
872          * I don't know if it's the right one. not documented.
873          */
874         if (!(handle->access & POLICY_VIEW_LOCAL_INFORMATION))
875                 return NT_STATUS_ACCESS_DENIED;
876
877         /* get the list of mapped groups (domain, local, builtin) */
878         become_root();
879         ret = pdb_enum_group_mapping(SID_NAME_UNKNOWN, &map, &num_entries, ENUM_ONLY_MAPPED);
880         unbecome_root();
881         if( !ret ) {
882                 DEBUG(3,("_lsa_enum_accounts: enumeration of groups failed!\n"));
883                 return NT_STATUS_OK;
884         }
885         
886
887         if (q_u->enum_context >= num_entries)
888                 return NT_STATUS_NO_MORE_ENTRIES;
889
890         sids->ptr_sid = (uint32 *)talloc_zero(p->mem_ctx, (num_entries-q_u->enum_context)*sizeof(uint32));
891         sids->sid = (DOM_SID2 *)talloc_zero(p->mem_ctx, (num_entries-q_u->enum_context)*sizeof(DOM_SID2));
892
893         if (sids->ptr_sid==NULL || sids->sid==NULL) {
894                 SAFE_FREE(map);
895                 return NT_STATUS_NO_MEMORY;
896         }
897
898         for (i=q_u->enum_context, j=0; i<num_entries; i++) {
899                 init_dom_sid2( &(*sids).sid[j],  &map[i].sid);
900                 (*sids).ptr_sid[j]=1;
901                 j++;
902         }
903
904         SAFE_FREE(map);
905
906         init_lsa_r_enum_accounts(r_u, j);
907
908         return NT_STATUS_OK;
909 }
910
911
912 NTSTATUS _lsa_unk_get_connuser(pipes_struct *p, LSA_Q_UNK_GET_CONNUSER *q_u, LSA_R_UNK_GET_CONNUSER *r_u)
913 {
914         fstring username, domname;
915         user_struct *vuser = get_valid_user_struct(p->vuid);
916   
917         if (vuser == NULL)
918                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
919   
920         fstrcpy(username, vuser->user.smb_name);
921         fstrcpy(domname, vuser->user.domain);
922   
923         r_u->ptr_user_name = 1;
924         init_unistr2(&r_u->uni2_user_name, username, UNI_STR_TERMINATE);
925         init_uni_hdr(&r_u->hdr_user_name, &r_u->uni2_user_name);
926
927         r_u->unk1 = 1;
928   
929         r_u->ptr_dom_name = 1;
930         init_unistr2(&r_u->uni2_dom_name, domname,  UNI_STR_TERMINATE);
931         init_uni_hdr(&r_u->hdr_dom_name, &r_u->uni2_dom_name);
932
933         r_u->status = NT_STATUS_OK;
934   
935         return r_u->status;
936 }
937
938 /***************************************************************************
939  
940  ***************************************************************************/
941
942 NTSTATUS _lsa_open_account(pipes_struct *p, LSA_Q_OPENACCOUNT *q_u, LSA_R_OPENACCOUNT *r_u)
943 {
944         struct lsa_info *handle;
945         struct lsa_info *info;
946
947         r_u->status = NT_STATUS_OK;
948
949         /* find the connection policy handle. */
950         if (!find_policy_by_hnd(p, &q_u->pol, (void **)&handle))
951                 return NT_STATUS_INVALID_HANDLE;
952
953         /* check if the user have enough rights */
954
955         /*
956          * I don't know if it's the right one. not documented.
957          * but guessed with rpcclient.
958          */
959         if (!(handle->access & POLICY_GET_PRIVATE_INFORMATION))
960                 return NT_STATUS_ACCESS_DENIED;
961
962         /* associate the user/group SID with the (unique) handle. */
963         if ((info = (struct lsa_info *)malloc(sizeof(struct lsa_info))) == NULL)
964                 return NT_STATUS_NO_MEMORY;
965
966         ZERO_STRUCTP(info);
967         info->sid = q_u->sid.sid;
968         info->access = q_u->access;
969
970         /* get a (unique) handle.  open a policy on it. */
971         if (!create_policy_hnd(p, &r_u->pol, free_lsa_info, (void *)info))
972                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
973
974         return r_u->status;
975 }
976
977 /***************************************************************************
978  For a given SID, enumerate all the privilege this account has.
979  ***************************************************************************/
980
981 NTSTATUS _lsa_enum_privsaccount(pipes_struct *p, prs_struct *ps, LSA_Q_ENUMPRIVSACCOUNT *q_u, LSA_R_ENUMPRIVSACCOUNT *r_u)
982 {
983         struct lsa_info *info=NULL;
984         GROUP_MAP map;
985         LUID_ATTR *set=NULL;
986
987         r_u->status = NT_STATUS_OK;
988
989         /* find the connection policy handle. */
990         if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info))
991                 return NT_STATUS_INVALID_HANDLE;
992
993         if (!pdb_getgrsid(&map, info->sid))
994                 return NT_STATUS_NO_SUCH_GROUP;
995
996 #if 0 /* privileges currently not implemented! */
997         DEBUG(10,("_lsa_enum_privsaccount: %d privileges\n", map.priv_set->count));
998         if (map.priv_set->count!=0) {
999         
1000                 set=(LUID_ATTR *)talloc(map.priv_set->mem_ctx, map.priv_set.count*sizeof(LUID_ATTR));
1001                 if (set == NULL) {
1002                         destroy_privilege(&map.priv_set);
1003                         return NT_STATUS_NO_MEMORY;
1004                 }
1005
1006                 for (i = 0; i < map.priv_set.count; i++) {
1007                         set[i].luid.low = map.priv_set->set[i].luid.low;
1008                         set[i].luid.high = map.priv_set->set[i].luid.high;
1009                         set[i].attr = map.priv_set->set[i].attr;
1010                         DEBUG(10,("_lsa_enum_privsaccount: priv %d: %d:%d:%d\n", i, 
1011                                    set[i].luid.high, set[i].luid.low, set[i].attr));
1012                 }
1013         }
1014
1015         init_lsa_r_enum_privsaccount(ps->mem_ctx, r_u, set, map.priv_set->count, 0);    
1016         destroy_privilege(&map.priv_set);       
1017 #endif
1018
1019         init_lsa_r_enum_privsaccount(ps->mem_ctx, r_u, set, 0, 0);
1020
1021         return r_u->status;
1022 }
1023
1024 /***************************************************************************
1025  
1026  ***************************************************************************/
1027
1028 NTSTATUS _lsa_getsystemaccount(pipes_struct *p, LSA_Q_GETSYSTEMACCOUNT *q_u, LSA_R_GETSYSTEMACCOUNT *r_u)
1029 {
1030         struct lsa_info *info=NULL;
1031         GROUP_MAP map;
1032         r_u->status = NT_STATUS_OK;
1033
1034         /* find the connection policy handle. */
1035         if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info))
1036                 return NT_STATUS_INVALID_HANDLE;
1037
1038         if (!pdb_getgrsid(&map, info->sid))
1039                 return NT_STATUS_NO_SUCH_GROUP;
1040
1041         /*
1042           0x01 -> Log on locally
1043           0x02 -> Access this computer from network
1044           0x04 -> Log on as a batch job
1045           0x10 -> Log on as a service
1046           
1047           they can be ORed together
1048         */
1049
1050         r_u->access = PR_LOG_ON_LOCALLY | PR_ACCESS_FROM_NETWORK;
1051
1052         return r_u->status;
1053 }
1054
1055 /***************************************************************************
1056   update the systemaccount information
1057  ***************************************************************************/
1058
1059 NTSTATUS _lsa_setsystemaccount(pipes_struct *p, LSA_Q_SETSYSTEMACCOUNT *q_u, LSA_R_SETSYSTEMACCOUNT *r_u)
1060 {
1061         struct lsa_info *info=NULL;
1062         GROUP_MAP map;
1063         r_u->status = NT_STATUS_OK;
1064
1065         /* find the connection policy handle. */
1066         if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info))
1067                 return NT_STATUS_INVALID_HANDLE;
1068
1069         if (!pdb_getgrsid(&map, info->sid))
1070                 return NT_STATUS_NO_SUCH_GROUP;
1071
1072         if(!pdb_update_group_mapping_entry(&map))
1073                 return NT_STATUS_NO_SUCH_GROUP;
1074
1075         return r_u->status;
1076 }
1077
1078 /***************************************************************************
1079  For a given SID, add some privileges.
1080  ***************************************************************************/
1081
1082 NTSTATUS _lsa_addprivs(pipes_struct *p, LSA_Q_ADDPRIVS *q_u, LSA_R_ADDPRIVS *r_u)
1083 {
1084 #if 0
1085         struct lsa_info *info = NULL;
1086         GROUP_MAP map;
1087         int i = 0;
1088         LUID_ATTR *luid_attr = NULL;
1089         PRIVILEGE_SET *set = NULL;
1090 #endif
1091
1092         r_u->status = NT_STATUS_OK;
1093
1094 #if 0 /* privileges are not implemented */
1095         /* find the connection policy handle. */
1096         if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info))
1097                 return NT_STATUS_INVALID_HANDLE;
1098
1099         if (!pdb_getgrsid(&map, info->sid))
1100                 return NT_STATUS_NO_SUCH_GROUP;
1101
1102         set = &q_u->set;
1103
1104         for (i = 0; i < set->count; i++) {
1105                 luid_attr = &set->set[i];
1106                 
1107                 /* check if the privilege is already there */
1108                 if (check_priv_in_privilege(map.priv_set, *luid_attr)){
1109                         destroy_privilege(&map.priv_set);
1110                 }
1111                 
1112                 add_privilege(map.priv_set, *luid_attr);
1113         }
1114
1115         if(!pdb_update_group_mapping_entry(&map))
1116                 return NT_STATUS_NO_SUCH_GROUP;
1117         
1118         destroy_privilege(&map.priv_set);       
1119
1120 #endif
1121         return r_u->status;
1122 }
1123
1124 /***************************************************************************
1125  For a given SID, remove some privileges.
1126  ***************************************************************************/
1127
1128 NTSTATUS _lsa_removeprivs(pipes_struct *p, LSA_Q_REMOVEPRIVS *q_u, LSA_R_REMOVEPRIVS *r_u)
1129 {
1130 #if 0
1131         struct lsa_info *info = NULL;
1132         GROUP_MAP map;
1133         int i=0;
1134         LUID_ATTR *luid_attr = NULL;
1135         PRIVILEGE_SET *set = NULL;
1136 #endif
1137
1138         r_u->status = NT_STATUS_OK;
1139
1140 #if 0 /* privileges are not implemented */
1141         /* find the connection policy handle. */
1142         if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info))
1143                 return NT_STATUS_INVALID_HANDLE;
1144
1145         if (!pdb_getgrsid(&map, info->sid))
1146                 return NT_STATUS_NO_SUCH_GROUP;
1147
1148         if (q_u->allrights != 0) {
1149                 /* log it and return, until I see one myself don't do anything */
1150                 DEBUG(5,("_lsa_removeprivs: trying to remove all privileges ?\n"));
1151                 return NT_STATUS_OK;
1152         }
1153
1154         if (q_u->ptr == 0) {
1155                 /* log it and return, until I see one myself don't do anything */
1156                 DEBUG(5,("_lsa_removeprivs: no privileges to remove ?\n"));
1157                 return NT_STATUS_OK;
1158         }
1159
1160         set = &q_u->set;
1161
1162         for (i = 0; i < set->count; i++) {
1163                 luid_attr = &set->set[i];
1164                 
1165                 /* if we don't have the privilege, we're trying to remove, give up */
1166                 /* what else can we do ??? JFM. */
1167                 if (!check_priv_in_privilege(map.priv_set, *luid_attr)){
1168                         destroy_privilege(&map.priv_set);
1169                         return NT_STATUS_NO_SUCH_PRIVILEGE;
1170                 }
1171                 
1172                 remove_privilege(map.priv_set, *luid_attr);
1173         }
1174
1175         if(!pdb_update_group_mapping_entry(&map))
1176                 return NT_STATUS_NO_SUCH_GROUP;
1177         
1178         destroy_privilege(&map.priv_set);       
1179 #endif
1180         return r_u->status;
1181 }
1182
1183 /***************************************************************************
1184  For a given SID, remove some privileges.
1185  ***************************************************************************/
1186
1187 NTSTATUS _lsa_query_secobj(pipes_struct *p, LSA_Q_QUERY_SEC_OBJ *q_u, LSA_R_QUERY_SEC_OBJ *r_u)
1188 {
1189         struct lsa_info *handle=NULL;
1190         SEC_DESC *psd = NULL;
1191         size_t sd_size;
1192         NTSTATUS status;
1193
1194         r_u->status = NT_STATUS_OK;
1195
1196         /* find the connection policy handle. */
1197         if (!find_policy_by_hnd(p, &q_u->pol, (void **)&handle))
1198                 return NT_STATUS_INVALID_HANDLE;
1199
1200         /* check if the user have enough rights */
1201         if (!(handle->access & POLICY_VIEW_LOCAL_INFORMATION))
1202                 return NT_STATUS_ACCESS_DENIED;
1203
1204
1205         switch (q_u->sec_info) {
1206         case 1:
1207                 /* SD contains only the owner */
1208
1209                 status=lsa_get_generic_sd(p->mem_ctx, &psd, &sd_size);
1210                 if(!NT_STATUS_IS_OK(status))
1211                         return NT_STATUS_NO_MEMORY;
1212
1213
1214                 if((r_u->buf = make_sec_desc_buf(p->mem_ctx, sd_size, psd)) == NULL)
1215                         return NT_STATUS_NO_MEMORY;
1216                 break;
1217         case 4:
1218                 /* SD contains only the ACL */
1219
1220                 status=lsa_get_generic_sd(p->mem_ctx, &psd, &sd_size);
1221                 if(!NT_STATUS_IS_OK(status))
1222                         return NT_STATUS_NO_MEMORY;
1223
1224                 if((r_u->buf = make_sec_desc_buf(p->mem_ctx, sd_size, psd)) == NULL)
1225                         return NT_STATUS_NO_MEMORY;
1226                 break;
1227         default:
1228                 return NT_STATUS_INVALID_LEVEL;
1229         }
1230
1231         r_u->ptr=1;
1232
1233         return r_u->status;
1234 }
1235
1236
1237 NTSTATUS _lsa_query_info2(pipes_struct *p, LSA_Q_QUERY_INFO2 *q_u, LSA_R_QUERY_INFO2 *r_u)
1238 {
1239         struct lsa_info *handle;
1240         const char *nb_name;
1241         char *dns_name = NULL;
1242         char *forest_name = NULL;
1243         DOM_SID *sid = NULL;
1244         struct uuid guid;
1245         fstring dnsdomname;
1246
1247         ZERO_STRUCT(guid);
1248         r_u->status = NT_STATUS_OK;
1249
1250         if (!find_policy_by_hnd(p, &q_u->pol, (void **)&handle))
1251                 return NT_STATUS_INVALID_HANDLE;
1252
1253         switch (q_u->info_class) {
1254         case 0x0c:
1255                 /* check if the user have enough rights */
1256                 if (!(handle->access & POLICY_VIEW_LOCAL_INFORMATION))
1257                         return NT_STATUS_ACCESS_DENIED;
1258
1259                 /* Request PolicyPrimaryDomainInformation. */
1260                 switch (lp_server_role()) {
1261                         case ROLE_DOMAIN_PDC:
1262                         case ROLE_DOMAIN_BDC:
1263                                 nb_name = get_global_sam_name();
1264                                 /* ugly temp hack for these next two */
1265
1266                                 /* This should be a 'netbios domain -> DNS domain' mapping */
1267                                 dnsdomname[0] = '\0';
1268                                 get_mydnsdomname(dnsdomname);
1269                                 strlower_m(dnsdomname);
1270                                 
1271                                 dns_name = dnsdomname;
1272                                 forest_name = dnsdomname;
1273
1274                                 sid = get_global_sam_sid();
1275                                 secrets_fetch_domain_guid(lp_workgroup(), &guid);
1276                                 break;
1277                         default:
1278                                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1279                 }
1280                 init_dns_dom_info(&r_u->info.dns_dom_info, nb_name, dns_name, 
1281                                   forest_name,&guid,sid);
1282                 break;
1283         default:
1284                 DEBUG(0,("_lsa_query_info2: unknown info level in Lsa Query: %d\n", q_u->info_class));
1285                 r_u->status = NT_STATUS_INVALID_INFO_CLASS;
1286                 break;
1287         }
1288
1289         if (NT_STATUS_IS_OK(r_u->status)) {
1290                 r_u->ptr = 0x1;
1291                 r_u->info_class = q_u->info_class;
1292         }
1293
1294         return r_u->status;
1295 }