r13458: Add parsing functions - but stub internals for lookupnames3 and 4.
[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  *  Copyright (C) Simo Sorce                        2003.
11  *  Copyright (C) Gerald (Jerry) Carter             2005.
12  *  Copyright (C) Volker Lendecke                   2005.
13  *
14  *  This program is free software; you can redistribute it and/or modify
15  *  it under the terms of the GNU General Public License as published by
16  *  the Free Software Foundation; either version 2 of the License, or
17  *  (at your option) any later version.
18  *  
19  *  This program is distributed in the hope that it will be useful,
20  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
21  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  *  GNU General Public License for more details.
23  *  
24  *  You should have received a copy of the GNU General Public License
25  *  along with this program; if not, write to the Free Software
26  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27  */
28
29 /* This is the implementation of the lsa server code. */
30
31 #include "includes.h"
32
33 #undef DBGC_CLASS
34 #define DBGC_CLASS DBGC_RPC_SRV
35
36 extern PRIVS privs[];
37
38 struct lsa_info {
39         DOM_SID sid;
40         uint32 access;
41 };
42
43 struct generic_mapping lsa_generic_mapping = {
44         POLICY_READ,
45         POLICY_WRITE,
46         POLICY_EXECUTE,
47         POLICY_ALL_ACCESS
48 };
49
50 /*******************************************************************
51  Function to free the per handle data.
52  ********************************************************************/
53
54 static void free_lsa_info(void *ptr)
55 {
56         struct lsa_info *lsa = (struct lsa_info *)ptr;
57
58         SAFE_FREE(lsa);
59 }
60
61 /***************************************************************************
62 Init dom_query
63  ***************************************************************************/
64
65 static void init_dom_query(DOM_QUERY *d_q, const char *dom_name, DOM_SID *dom_sid)
66 {
67         d_q->buffer_dom_name = (dom_name != NULL) ? 1 : 0; /* domain buffer pointer */
68         d_q->buffer_dom_sid = (dom_sid != NULL) ? 1 : 0;  /* domain sid pointer */
69
70         /* this string is supposed to be non-null terminated. */
71         /* But the maxlen in this UNISTR2 must include the terminating null. */
72         init_unistr2(&d_q->uni_domain_name, dom_name, UNI_BROKEN_NON_NULL);
73
74         /*
75          * I'm not sure why this really odd combination of length
76          * values works, but it does appear to. I need to look at
77          * this *much* more closely - but at the moment leave alone
78          * until it's understood. This allows a W2k client to join
79          * a domain with both odd and even length names... JRA.
80          */
81
82         /*
83          * IMPORTANT NOTE !!!!
84          * The two fields below probably are reversed in meaning, ie.
85          * the first field is probably the str_len, the second the max
86          * len. Both are measured in bytes anyway.
87          */
88
89         d_q->uni_dom_str_len = d_q->uni_domain_name.uni_max_len * 2;
90         d_q->uni_dom_max_len = d_q->uni_domain_name.uni_str_len * 2;
91
92         if (dom_sid != NULL)
93                 init_dom_sid2(&d_q->dom_sid, dom_sid);
94 }
95
96 /***************************************************************************
97  init_dom_ref - adds a domain if it's not already in, returns the index.
98 ***************************************************************************/
99
100 static int init_dom_ref(DOM_R_REF *ref, const char *dom_name, DOM_SID *dom_sid)
101 {
102         int num = 0;
103
104         if (dom_name != NULL) {
105                 for (num = 0; num < ref->num_ref_doms_1; num++) {
106                         if (sid_equal(dom_sid, &ref->ref_dom[num].ref_dom.sid))
107                                 return num;
108                 }
109         } else {
110                 num = ref->num_ref_doms_1;
111         }
112
113         if (num >= MAX_REF_DOMAINS) {
114                 /* index not found, already at maximum domain limit */
115                 return -1;
116         }
117
118         ref->num_ref_doms_1 = num+1;
119         ref->ptr_ref_dom  = 1;
120         ref->max_entries = MAX_REF_DOMAINS;
121         ref->num_ref_doms_2 = num+1;
122
123         ref->hdr_ref_dom[num].ptr_dom_sid = dom_sid != NULL ? 1 : 0;
124
125         init_unistr2(&ref->ref_dom[num].uni_dom_name, dom_name, UNI_FLAGS_NONE);
126         init_uni_hdr(&ref->hdr_ref_dom[num].hdr_dom_name, &ref->ref_dom[num].uni_dom_name);
127
128         init_dom_sid2(&ref->ref_dom[num].ref_dom, dom_sid );
129
130         return num;
131 }
132
133 /***************************************************************************
134  init_lsa_rids
135  ***************************************************************************/
136
137 static int init_lsa_rids(TALLOC_CTX *mem_ctx,
138                           DOM_R_REF *ref, DOM_RID *prid,
139                           int num_entries, UNISTR2 *name,
140                           int flags)
141 {
142         int mapped_count, i;
143
144         SMB_ASSERT(num_entries <= MAX_LOOKUP_SIDS);
145
146         mapped_count = 0;
147
148         become_root(); /* lookup_name can require root privs */
149
150         for (i = 0; i < num_entries; i++) {
151                 DOM_SID sid;
152                 uint32 rid;
153                 int dom_idx;
154                 char *full_name;
155                 const char *domain;
156                 enum SID_NAME_USE type = SID_NAME_UNKNOWN;
157
158                 /* Split name into domain and user component */
159
160                 full_name = rpcstr_pull_unistr2_talloc(mem_ctx, &name[i]);
161                 if (full_name == NULL) {
162                         DEBUG(0, ("pull_ucs2_talloc failed\n"));
163                         return 0;
164                 }
165
166                 DEBUG(5, ("init_lsa_rids: looking up name %s\n", full_name));
167
168                 /* We can ignore the result of lookup_name, it will not touch
169                    "type" if it's not successful */
170
171                 lookup_name(mem_ctx, full_name, flags, &domain, NULL,
172                             &sid, &type);
173
174
175                 switch (type) {
176                 case SID_NAME_USER:
177                 case SID_NAME_DOM_GRP:
178                 case SID_NAME_DOMAIN:
179                 case SID_NAME_ALIAS:
180                 case SID_NAME_WKN_GRP:
181                         DEBUG(5, ("init_lsa_rids: %s found\n", full_name));
182                         /* Leave these unchanged */
183                         break;
184                 default:
185                         /* Don't hand out anything but the list above */
186                         DEBUG(5, ("init_lsa_rids: %s not found\n", full_name));
187                         type = SID_NAME_UNKNOWN;
188                         break;
189                 }
190
191                 rid = 0;
192                 dom_idx = -1;
193
194                 if (type != SID_NAME_UNKNOWN) {
195                         sid_split_rid(&sid, &rid);
196                         dom_idx = init_dom_ref(ref, domain, &sid);
197                         mapped_count++;
198                 }
199
200                 init_dom_rid(&prid[i], rid, type, dom_idx);
201         }
202
203         unbecome_root();
204
205         return mapped_count;
206 }
207
208 /***************************************************************************
209  init_reply_lookup_names
210  ***************************************************************************/
211
212 static void init_reply_lookup_names(LSA_R_LOOKUP_NAMES *r_l,
213                 DOM_R_REF *ref, uint32 num_entries,
214                 DOM_RID *rid, uint32 mapped_count)
215 {
216         r_l->ptr_dom_ref  = 1;
217         r_l->dom_ref      = ref;
218
219         r_l->num_entries  = num_entries;
220         r_l->ptr_entries  = 1;
221         r_l->num_entries2 = num_entries;
222         r_l->dom_rid      = rid;
223
224         r_l->mapped_count = mapped_count;
225 }
226
227 /***************************************************************************
228  init_reply_lookup_names2
229  ***************************************************************************/
230
231 static void init_reply_lookup_names2(LSA_R_LOOKUP_NAMES2 *r_l,
232                 DOM_R_REF *ref, uint32 num_entries,
233                 DOM_RID2 *rid, uint32 mapped_count)
234 {
235         r_l->ptr_dom_ref  = 1;
236         r_l->dom_ref      = ref;
237
238         r_l->num_entries  = num_entries;
239         r_l->ptr_entries  = 1;
240         r_l->num_entries2 = num_entries;
241         r_l->dom_rid      = rid;
242
243         r_l->mapped_count = mapped_count;
244 }
245
246 /***************************************************************************
247  Init_reply_lookup_sids.
248  ***************************************************************************/
249
250 static void init_reply_lookup_sids2(LSA_R_LOOKUP_SIDS2 *r_l,
251                                 DOM_R_REF *ref,
252                                 LSA_TRANS_NAME_ENUM2 *names,
253                                 uint32 mapped_count)
254 {
255         r_l->ptr_dom_ref  = ref ? 1 : 0;
256         r_l->dom_ref      = ref;
257         r_l->names        = names;
258         r_l->mapped_count = mapped_count;
259 }
260
261 /***************************************************************************
262  Init_reply_lookup_sids.
263  ***************************************************************************/
264
265 static void init_reply_lookup_sids3(LSA_R_LOOKUP_SIDS3 *r_l,
266                                 DOM_R_REF *ref,
267                                 LSA_TRANS_NAME_ENUM2 *names,
268                                 uint32 mapped_count)
269 {
270         r_l->ptr_dom_ref  = ref ? 1 : 0;
271         r_l->dom_ref      = ref;
272         r_l->names        = names;
273         r_l->mapped_count = mapped_count;
274 }
275
276 /***************************************************************************
277  Init_reply_lookup_sids.
278  ***************************************************************************/
279
280 static NTSTATUS init_reply_lookup_sids(TALLOC_CTX *mem_ctx,
281                                 LSA_R_LOOKUP_SIDS *r_l,
282                                 DOM_R_REF *ref,
283                                 LSA_TRANS_NAME_ENUM2 *names,
284                                 uint32 mapped_count)
285 {
286         LSA_TRANS_NAME_ENUM *oldnames = TALLOC_ZERO_P(mem_ctx, LSA_TRANS_NAME_ENUM);
287
288         if (!oldnames) {
289                 return NT_STATUS_NO_MEMORY;
290         }
291
292         oldnames->num_entries = names->num_entries;
293         oldnames->ptr_trans_names = names->ptr_trans_names;
294         oldnames->num_entries2 = names->num_entries2;
295         oldnames->uni_name = names->uni_name;
296
297         if (names->num_entries) {
298                 int i;
299
300                 oldnames->name = TALLOC_ARRAY(oldnames, LSA_TRANS_NAME, names->num_entries);
301
302                 if (!oldnames->name) {
303                         return NT_STATUS_NO_MEMORY;
304                 }
305                 for (i = 0; i < names->num_entries; i++) {
306                         oldnames->name[i].sid_name_use = names->name[i].sid_name_use;
307                         oldnames->name[i].hdr_name = names->name[i].hdr_name;
308                         oldnames->name[i].domain_idx = names->name[i].domain_idx;
309                 }
310         }
311
312         r_l->ptr_dom_ref  = ref ? 1 : 0;
313         r_l->dom_ref      = ref;
314         r_l->names        = oldnames;
315         r_l->mapped_count = mapped_count;
316         return NT_STATUS_OK;
317 }
318
319 static NTSTATUS lsa_get_generic_sd(TALLOC_CTX *mem_ctx, SEC_DESC **sd, size_t *sd_size)
320 {
321         DOM_SID local_adm_sid;
322         DOM_SID adm_sid;
323
324         SEC_ACE ace[3];
325         SEC_ACCESS mask;
326
327         SEC_ACL *psa = NULL;
328
329         init_sec_access(&mask, POLICY_EXECUTE);
330         init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
331
332         sid_copy(&adm_sid, get_global_sam_sid());
333         sid_append_rid(&adm_sid, DOMAIN_GROUP_RID_ADMINS);
334         init_sec_access(&mask, POLICY_ALL_ACCESS);
335         init_sec_ace(&ace[1], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
336
337         sid_copy(&local_adm_sid, &global_sid_Builtin);
338         sid_append_rid(&local_adm_sid, BUILTIN_ALIAS_RID_ADMINS);
339         init_sec_access(&mask, POLICY_ALL_ACCESS);
340         init_sec_ace(&ace[2], &local_adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
341
342         if((psa = make_sec_acl(mem_ctx, NT4_ACL_REVISION, 3, ace)) == NULL)
343                 return NT_STATUS_NO_MEMORY;
344
345         if((*sd = make_sec_desc(mem_ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, &adm_sid, NULL, NULL, psa, sd_size)) == NULL)
346                 return NT_STATUS_NO_MEMORY;
347
348         return NT_STATUS_OK;
349 }
350
351 #if 0   /* AD DC work in ongoing in Samba 4 */
352
353 /***************************************************************************
354  Init_dns_dom_info.
355 ***************************************************************************/
356
357 static void init_dns_dom_info(LSA_DNS_DOM_INFO *r_l, const char *nb_name,
358                               const char *dns_name, const char *forest_name,
359                               struct uuid *dom_guid, DOM_SID *dom_sid)
360 {
361         if (nb_name && *nb_name) {
362                 init_unistr2(&r_l->uni_nb_dom_name, nb_name, UNI_FLAGS_NONE);
363                 init_uni_hdr(&r_l->hdr_nb_dom_name, &r_l->uni_nb_dom_name);
364                 r_l->hdr_nb_dom_name.uni_max_len += 2;
365                 r_l->uni_nb_dom_name.uni_max_len += 1;
366         }
367         
368         if (dns_name && *dns_name) {
369                 init_unistr2(&r_l->uni_dns_dom_name, dns_name, UNI_FLAGS_NONE);
370                 init_uni_hdr(&r_l->hdr_dns_dom_name, &r_l->uni_dns_dom_name);
371                 r_l->hdr_dns_dom_name.uni_max_len += 2;
372                 r_l->uni_dns_dom_name.uni_max_len += 1;
373         }
374
375         if (forest_name && *forest_name) {
376                 init_unistr2(&r_l->uni_forest_name, forest_name, UNI_FLAGS_NONE);
377                 init_uni_hdr(&r_l->hdr_forest_name, &r_l->uni_forest_name);
378                 r_l->hdr_forest_name.uni_max_len += 2;
379                 r_l->uni_forest_name.uni_max_len += 1;
380         }
381
382         /* how do we init the guid ? probably should write an init fn */
383         if (dom_guid) {
384                 memcpy(&r_l->dom_guid, dom_guid, sizeof(struct uuid));
385         }
386         
387         if (dom_sid) {
388                 r_l->ptr_dom_sid = 1;
389                 init_dom_sid2(&r_l->dom_sid, dom_sid);
390         }
391 }
392 #endif  /* AD DC work in ongoing in Samba 4 */
393
394
395 /***************************************************************************
396  _lsa_open_policy2.
397  ***************************************************************************/
398
399 NTSTATUS _lsa_open_policy2(pipes_struct *p, LSA_Q_OPEN_POL2 *q_u, LSA_R_OPEN_POL2 *r_u)
400 {
401         struct lsa_info *info;
402         SEC_DESC *psd = NULL;
403         size_t sd_size;
404         uint32 des_access=q_u->des_access;
405         uint32 acc_granted;
406         NTSTATUS status;
407
408
409         /* map the generic bits to the lsa policy ones */
410         se_map_generic(&des_access, &lsa_generic_mapping);
411
412         /* get the generic lsa policy SD until we store it */
413         lsa_get_generic_sd(p->mem_ctx, &psd, &sd_size);
414
415         if(!se_access_check(psd, p->pipe_user.nt_user_token, des_access, &acc_granted, &status)) {
416                 if (geteuid() != 0) {
417                         return status;
418                 }
419                 DEBUG(4,("ACCESS should be DENIED (granted: %#010x;  required: %#010x)\n",
420                          acc_granted, des_access));
421                 DEBUGADD(4,("but overwritten by euid == 0\n"));
422         }
423
424         /* This is needed for lsa_open_account and rpcclient .... :-) */
425
426         if (geteuid() == 0)
427                 acc_granted = POLICY_ALL_ACCESS;
428
429         /* associate the domain SID with the (unique) handle. */
430         if ((info = SMB_MALLOC_P(struct lsa_info)) == NULL)
431                 return NT_STATUS_NO_MEMORY;
432
433         ZERO_STRUCTP(info);
434         sid_copy(&info->sid,get_global_sam_sid());
435         info->access = acc_granted;
436
437         /* set up the LSA QUERY INFO response */
438         if (!create_policy_hnd(p, &r_u->pol, free_lsa_info, (void *)info))
439                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
440
441         return NT_STATUS_OK;
442 }
443
444 /***************************************************************************
445  _lsa_open_policy
446  ***************************************************************************/
447
448 NTSTATUS _lsa_open_policy(pipes_struct *p, LSA_Q_OPEN_POL *q_u, LSA_R_OPEN_POL *r_u)
449 {
450         struct lsa_info *info;
451         SEC_DESC *psd = NULL;
452         size_t sd_size;
453         uint32 des_access=q_u->des_access;
454         uint32 acc_granted;
455         NTSTATUS status;
456
457
458         /* map the generic bits to the lsa policy ones */
459         se_map_generic(&des_access, &lsa_generic_mapping);
460
461         /* get the generic lsa policy SD until we store it */
462         lsa_get_generic_sd(p->mem_ctx, &psd, &sd_size);
463
464         if(!se_access_check(psd, p->pipe_user.nt_user_token, des_access, &acc_granted, &status)) {
465                 if (geteuid() != 0) {
466                         return status;
467                 }
468                 DEBUG(4,("ACCESS should be DENIED (granted: %#010x;  required: %#010x)\n",
469                          acc_granted, des_access));
470                 DEBUGADD(4,("but overwritten by euid == 0\n"));
471                 acc_granted = des_access;
472         }
473
474         /* associate the domain SID with the (unique) handle. */
475         if ((info = SMB_MALLOC_P(struct lsa_info)) == NULL)
476                 return NT_STATUS_NO_MEMORY;
477
478         ZERO_STRUCTP(info);
479         sid_copy(&info->sid,get_global_sam_sid());
480         info->access = acc_granted;
481
482         /* set up the LSA QUERY INFO response */
483         if (!create_policy_hnd(p, &r_u->pol, free_lsa_info, (void *)info))
484                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
485
486         return NT_STATUS_OK;
487 }
488
489 /***************************************************************************
490  _lsa_enum_trust_dom - this needs fixing to do more than return NULL ! JRA.
491  ufff, done :)  mimir
492  ***************************************************************************/
493
494 NTSTATUS _lsa_enum_trust_dom(pipes_struct *p, LSA_Q_ENUM_TRUST_DOM *q_u,
495                              LSA_R_ENUM_TRUST_DOM *r_u)
496 {
497         struct lsa_info *info;
498         uint32 next_idx;
499         struct trustdom_info **domains;
500
501         /*
502          * preferred length is set to 5 as a "our" preferred length
503          * nt sets this parameter to 2
504          * update (20.08.2002): it's not preferred length, but preferred size!
505          * it needs further investigation how to optimally choose this value
506          */
507         uint32 max_num_domains =
508                 q_u->preferred_len < 5 ? q_u->preferred_len : 10;
509         uint32 num_domains;
510         NTSTATUS nt_status;
511         uint32 num_thistime;
512
513         if (!find_policy_by_hnd(p, &q_u->pol, (void **)(void *)&info))
514                 return NT_STATUS_INVALID_HANDLE;
515
516         /* check if the user have enough rights */
517         if (!(info->access & POLICY_VIEW_LOCAL_INFORMATION))
518                 return NT_STATUS_ACCESS_DENIED;
519
520         nt_status = secrets_trusted_domains(p->mem_ctx, &num_domains,
521                                             &domains);
522
523         if (!NT_STATUS_IS_OK(nt_status)) {
524                 return nt_status;
525         }
526
527         if (q_u->enum_context < num_domains) {
528                 num_thistime = MIN(num_domains, max_num_domains);
529
530                 r_u->status = STATUS_MORE_ENTRIES;
531
532                 if (q_u->enum_context + num_thistime > num_domains) {
533                         num_thistime = num_domains - q_u->enum_context;
534                         r_u->status = NT_STATUS_OK;
535                 }
536
537                 next_idx = q_u->enum_context + num_thistime;
538         } else {
539                 num_thistime = 0;
540                 next_idx = 0xffffffff;
541                 r_u->status = NT_STATUS_NO_MORE_ENTRIES;
542         }
543                 
544         /* set up the lsa_enum_trust_dom response */
545
546         init_r_enum_trust_dom(p->mem_ctx, r_u, next_idx,
547                               num_thistime, domains+q_u->enum_context);
548
549         return r_u->status;
550 }
551
552 /***************************************************************************
553  _lsa_query_info. See the POLICY_INFOMATION_CLASS docs at msdn.
554  ***************************************************************************/
555
556 NTSTATUS _lsa_query_info(pipes_struct *p, LSA_Q_QUERY_INFO *q_u, LSA_R_QUERY_INFO *r_u)
557 {
558         struct lsa_info *handle;
559         LSA_INFO_UNION *info = &r_u->dom;
560         DOM_SID domain_sid;
561         const char *name;
562         DOM_SID *sid = NULL;
563
564         r_u->status = NT_STATUS_OK;
565
566         if (!find_policy_by_hnd(p, &q_u->pol, (void **)(void *)&handle))
567                 return NT_STATUS_INVALID_HANDLE;
568
569         switch (q_u->info_class) {
570         case 0x02:
571                 {
572                 unsigned int i;
573                 /* check if the user have enough rights */
574                 if (!(handle->access & POLICY_VIEW_AUDIT_INFORMATION))
575                         return NT_STATUS_ACCESS_DENIED;
576
577                 /* fake info: We audit everything. ;) */
578                 info->id2.auditing_enabled = 1;
579                 info->id2.count1 = 7;
580                 info->id2.count2 = 7;
581                 if ((info->id2.auditsettings = TALLOC_ARRAY(p->mem_ctx,uint32, 7)) == NULL)
582                         return NT_STATUS_NO_MEMORY;
583                 for (i = 0; i < 7; i++)
584                         info->id2.auditsettings[i] = 3;
585                 break;
586                 }
587         case 0x03:
588                 /* check if the user have enough rights */
589                 if (!(handle->access & POLICY_VIEW_LOCAL_INFORMATION))
590                         return NT_STATUS_ACCESS_DENIED;
591
592                 /* Request PolicyPrimaryDomainInformation. */
593                 switch (lp_server_role()) {
594                         case ROLE_DOMAIN_PDC:
595                         case ROLE_DOMAIN_BDC:
596                                 name = get_global_sam_name();
597                                 sid = get_global_sam_sid();
598                                 break;
599                         case ROLE_DOMAIN_MEMBER:
600                                 name = lp_workgroup();
601                                 /* We need to return the Domain SID here. */
602                                 if (secrets_fetch_domain_sid(lp_workgroup(), &domain_sid))
603                                         sid = &domain_sid;
604                                 else
605                                         return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
606                                 break;
607                         case ROLE_STANDALONE:
608                                 name = lp_workgroup();
609                                 sid = NULL;
610                                 break;
611                         default:
612                                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
613                 }
614                 init_dom_query(&r_u->dom.id3, name, sid);
615                 break;
616         case 0x05:
617                 /* check if the user have enough rights */
618                 if (!(handle->access & POLICY_VIEW_LOCAL_INFORMATION))
619                         return NT_STATUS_ACCESS_DENIED;
620
621                 /* Request PolicyAccountDomainInformation. */
622                 name = get_global_sam_name();
623                 sid = get_global_sam_sid();
624                 init_dom_query(&r_u->dom.id5, name, sid);
625                 break;
626         case 0x06:
627                 /* check if the user have enough rights */
628                 if (!(handle->access & POLICY_VIEW_LOCAL_INFORMATION))
629                         return NT_STATUS_ACCESS_DENIED;
630
631                 switch (lp_server_role()) {
632                         case ROLE_DOMAIN_BDC:
633                                 /*
634                                  * only a BDC is a backup controller
635                                  * of the domain, it controls.
636                                  */
637                                 info->id6.server_role = 2;
638                                 break;
639                         default:
640                                 /*
641                                  * any other role is a primary
642                                  * of the domain, it controls.
643                                  */
644                                 info->id6.server_role = 3;
645                                 break; 
646                 }
647                 break;
648         default:
649                 DEBUG(0,("_lsa_query_info: unknown info level in Lsa Query: %d\n", q_u->info_class));
650                 r_u->status = NT_STATUS_INVALID_INFO_CLASS;
651                 break;
652         }
653
654         if (NT_STATUS_IS_OK(r_u->status)) {
655                 r_u->undoc_buffer = 0x22000000; /* bizarre */
656                 r_u->info_class = q_u->info_class;
657         }
658
659         return r_u->status;
660 }
661
662 /***************************************************************************
663  _lsa_lookup_sids_internal
664  ***************************************************************************/
665
666 static NTSTATUS _lsa_lookup_sids_internal(pipes_struct *p,
667                                 uint16 level,                           /* input */
668                                 int num_sids,                           /* input */
669                                 const DOM_SID2 *sid,                    /* input */
670                                 DOM_R_REF **pp_ref,                     /* output */
671                                 LSA_TRANS_NAME_ENUM2 **pp_names,        /* output */
672                                 uint32 *pp_mapped_count)
673 {
674         NTSTATUS status;
675         int i;
676         const DOM_SID **sids = NULL;
677         LSA_TRANS_NAME_ENUM2 *names = NULL;
678         DOM_R_REF *ref = NULL;
679         uint32 mapped_count = 0;
680         struct lsa_dom_info *dom_infos = NULL;
681         struct lsa_name_info *name_infos = NULL;
682
683         *pp_mapped_count = 0;
684         *pp_ref = NULL;
685         *pp_names = NULL;
686         
687         names = TALLOC_ZERO_P(p->mem_ctx, LSA_TRANS_NAME_ENUM2);
688         sids = TALLOC_ARRAY(p->mem_ctx, const DOM_SID *, num_sids);
689         ref = TALLOC_ZERO_P(p->mem_ctx, DOM_R_REF);
690
691         if (sids == NULL || names == NULL || ref == NULL) {
692                 return NT_STATUS_NO_MEMORY;
693         }
694
695         for (i=0; i<num_sids; i++) {
696                 sids[i] = &sid[i].sid;
697         }
698
699         status = lookup_sids(p->mem_ctx, num_sids, sids, level,
700                                   &dom_infos, &name_infos);
701
702         if (!NT_STATUS_IS_OK(status)) {
703                 return status;
704         }
705
706         if (num_sids > 0) {
707                 names->name = TALLOC_ARRAY(names, LSA_TRANS_NAME2, num_sids);
708                 names->uni_name = TALLOC_ARRAY(names, UNISTR2, num_sids);
709                 if ((names->name == NULL) || (names->uni_name == NULL)) {
710                         return NT_STATUS_NO_MEMORY;
711                 }
712         }
713
714         for (i=0; i<MAX_REF_DOMAINS; i++) {
715
716                 if (!dom_infos[i].valid) {
717                         break;
718                 }
719
720                 if (init_dom_ref(ref, dom_infos[i].name,
721                                  &dom_infos[i].sid) != i) {
722                         DEBUG(0, ("Domain %s mentioned twice??\n",
723                                   dom_infos[i].name));
724                         return NT_STATUS_INTERNAL_ERROR;
725                 }
726         }
727
728         for (i=0; i<num_sids; i++) {
729                 struct lsa_name_info *name = &name_infos[i];
730
731                 if (name->type == SID_NAME_UNKNOWN) {
732                         name->dom_idx = -1;
733                         name->name = talloc_asprintf(p->mem_ctx, "%8.8x",
734                                                      name->rid);
735                         if (name->name == NULL) {
736                                 return NT_STATUS_NO_MEMORY;
737                         }
738                 } else {
739                         mapped_count += 1;
740                 }
741                 init_lsa_trans_name2(&names->name[i], &names->uni_name[i],
742                                     name->type, name->name, name->dom_idx);
743         }
744
745         names->num_entries = num_sids;
746         names->ptr_trans_names = 1;
747         names->num_entries2 = num_sids;
748
749         status = NT_STATUS_NONE_MAPPED;
750         if (mapped_count > 0) {
751                 status = (mapped_count < num_sids) ?
752                         STATUS_SOME_UNMAPPED : NT_STATUS_OK;
753         }
754
755         DEBUG(10, ("num_sids %d, mapped_count %d, status %s\n",
756                    num_sids, mapped_count, nt_errstr(status)));
757
758         *pp_mapped_count = mapped_count;
759         *pp_ref = ref;
760         *pp_names = names;
761
762         return status;
763 }
764
765 /***************************************************************************
766  _lsa_lookup_sids
767  ***************************************************************************/
768
769 NTSTATUS _lsa_lookup_sids(pipes_struct *p,
770                           LSA_Q_LOOKUP_SIDS *q_u,
771                           LSA_R_LOOKUP_SIDS *r_u)
772 {
773         struct lsa_info *handle;
774         int num_sids = q_u->sids.num_entries;
775         uint32 mapped_count = 0;
776         DOM_R_REF *ref = NULL;
777         LSA_TRANS_NAME_ENUM2 *names = NULL;
778         NTSTATUS status;
779
780         if ((q_u->level < 1) || (q_u->level > 6)) {
781                 return NT_STATUS_INVALID_PARAMETER;
782         }
783
784         if (!find_policy_by_hnd(p, &q_u->pol, (void **)(void *)&handle)) {
785                 return NT_STATUS_INVALID_HANDLE;
786         }
787
788         /* check if the user has enough rights */
789         if (!(handle->access & POLICY_LOOKUP_NAMES)) {
790                 return NT_STATUS_ACCESS_DENIED;
791         }
792
793         if (num_sids >  MAX_LOOKUP_SIDS) {
794                 DEBUG(5,("_lsa_lookup_sids: limit of %d exceeded, requested %d\n",
795                          MAX_LOOKUP_SIDS, num_sids));
796                 return NT_STATUS_NONE_MAPPED;
797         }
798
799         r_u->status = _lsa_lookup_sids_internal(p,
800                                                 q_u->level,
801                                                 num_sids, 
802                                                 q_u->sids.sid,
803                                                 &ref,
804                                                 &names,
805                                                 &mapped_count);
806
807         /* Convert from LSA_TRANS_NAME_ENUM2 to LSA_TRANS_NAME_ENUM */
808
809         status = init_reply_lookup_sids(p->mem_ctx, r_u, ref, names, mapped_count);
810         if (!NT_STATUS_IS_OK(status)) {
811                 return status;
812         }
813         return r_u->status;
814 }
815
816 /***************************************************************************
817  _lsa_lookup_sids2
818  ***************************************************************************/
819
820 NTSTATUS _lsa_lookup_sids2(pipes_struct *p,
821                           LSA_Q_LOOKUP_SIDS2 *q_u,
822                           LSA_R_LOOKUP_SIDS2 *r_u)
823 {
824         struct lsa_info *handle;
825         int num_sids = q_u->sids.num_entries;
826         uint32 mapped_count = 0;
827         DOM_R_REF *ref = NULL;
828         LSA_TRANS_NAME_ENUM2 *names = NULL;
829
830         if ((q_u->level < 1) || (q_u->level > 6)) {
831                 return NT_STATUS_INVALID_PARAMETER;
832         }
833
834         if (!find_policy_by_hnd(p, &q_u->pol, (void **)(void *)&handle)) {
835                 return NT_STATUS_INVALID_HANDLE;
836         }
837
838         /* check if the user have enough rights */
839         if (!(handle->access & POLICY_LOOKUP_NAMES)) {
840                 return NT_STATUS_ACCESS_DENIED;
841         }
842
843         if (num_sids >  MAX_LOOKUP_SIDS) {
844                 DEBUG(5,("_lsa_lookup_sids2: limit of %d exceeded, requested %d\n",
845                          MAX_LOOKUP_SIDS, num_sids));
846                 return NT_STATUS_NONE_MAPPED;
847         }
848
849         r_u->status = _lsa_lookup_sids_internal(p,
850                                                 q_u->level,
851                                                 num_sids, 
852                                                 q_u->sids.sid,
853                                                 &ref,
854                                                 &names,
855                                                 &mapped_count);
856
857         init_reply_lookup_sids2(r_u, ref, names, mapped_count);
858         return r_u->status;
859 }
860
861 /***************************************************************************
862  _lsa_lookup_sida3
863  ***************************************************************************/
864
865 NTSTATUS _lsa_lookup_sids3(pipes_struct *p,
866                           LSA_Q_LOOKUP_SIDS3 *q_u,
867                           LSA_R_LOOKUP_SIDS3 *r_u)
868 {
869         int num_sids = q_u->sids.num_entries;
870         uint32 mapped_count = 0;
871         DOM_R_REF *ref = NULL;
872         LSA_TRANS_NAME_ENUM2 *names = NULL;
873
874         if ((q_u->level < 1) || (q_u->level > 6)) {
875                 return NT_STATUS_INVALID_PARAMETER;
876         }
877
878         /* No policy handle on this call. Restrict to crypto connections. */
879         if (p->auth.auth_type != PIPE_AUTH_TYPE_SCHANNEL) {
880                 DEBUG(0,("_lsa_lookup_sids3: client %s not using schannel for netlogon\n",
881                         get_remote_machine_name() ));
882                 return NT_STATUS_INVALID_PARAMETER;
883         }
884
885         if (num_sids >  MAX_LOOKUP_SIDS) {
886                 DEBUG(5,("_lsa_lookup_sids3: limit of %d exceeded, requested %d\n",
887                          MAX_LOOKUP_SIDS, num_sids));
888                 return NT_STATUS_NONE_MAPPED;
889         }
890
891         r_u->status = _lsa_lookup_sids_internal(p,
892                                                 q_u->level,
893                                                 num_sids, 
894                                                 q_u->sids.sid,
895                                                 &ref,
896                                                 &names,
897                                                 &mapped_count);
898
899         init_reply_lookup_sids3(r_u, ref, names, mapped_count);
900         return r_u->status;
901 }
902
903 /***************************************************************************
904 lsa_reply_lookup_names
905  ***************************************************************************/
906
907 NTSTATUS _lsa_lookup_names(pipes_struct *p,LSA_Q_LOOKUP_NAMES *q_u, LSA_R_LOOKUP_NAMES *r_u)
908 {
909         struct lsa_info *handle;
910         UNISTR2 *names = q_u->uni_name;
911         int num_entries = q_u->num_entries;
912         DOM_R_REF *ref;
913         DOM_RID *rids;
914         uint32 mapped_count = 0;
915         int flags = 0;
916
917         if (num_entries >  MAX_LOOKUP_SIDS) {
918                 num_entries = MAX_LOOKUP_SIDS;
919                 DEBUG(5,("_lsa_lookup_names: truncating name lookup list to %d\n", num_entries));
920         }
921                 
922         /* Probably the lookup_level is some sort of bitmask. */
923         if (q_u->lookup_level == 1) {
924                 flags = LOOKUP_NAME_ALL;
925         }
926
927         ref = TALLOC_ZERO_P(p->mem_ctx, DOM_R_REF);
928         rids = TALLOC_ZERO_ARRAY(p->mem_ctx, DOM_RID, num_entries);
929
930         if (!find_policy_by_hnd(p, &q_u->pol, (void **)(void *)&handle)) {
931                 r_u->status = NT_STATUS_INVALID_HANDLE;
932                 goto done;
933         }
934
935         /* check if the user have enough rights */
936         if (!(handle->access & POLICY_LOOKUP_NAMES)) {
937                 r_u->status = NT_STATUS_ACCESS_DENIED;
938                 goto done;
939         }
940
941         if (!ref || !rids)
942                 return NT_STATUS_NO_MEMORY;
943
944         /* set up the LSA Lookup RIDs response */
945         mapped_count = init_lsa_rids(p->mem_ctx, ref, rids, num_entries,
946                                       names, flags);
947 done:
948
949         if (NT_STATUS_IS_OK(r_u->status)) {
950                 if (mapped_count == 0)
951                         r_u->status = NT_STATUS_NONE_MAPPED;
952                 else if (mapped_count != num_entries)
953                         r_u->status = STATUS_SOME_UNMAPPED;
954         }
955         init_reply_lookup_names(r_u, ref, num_entries, rids, mapped_count);
956
957         return r_u->status;
958 }
959
960 /***************************************************************************
961 lsa_reply_lookup_names2
962  ***************************************************************************/
963
964 NTSTATUS _lsa_lookup_names2(pipes_struct *p, LSA_Q_LOOKUP_NAMES2 *q_u, LSA_R_LOOKUP_NAMES2 *r_u)
965 {
966         struct lsa_info *handle;
967         UNISTR2 *names = q_u->uni_name;
968         int num_entries = q_u->num_entries;
969         DOM_R_REF *ref;
970         DOM_RID *rids;
971         DOM_RID2 *rids2;
972         int i;
973         uint32 mapped_count = 0;
974         int flags = 0;
975
976         if (num_entries >  MAX_LOOKUP_SIDS) {
977                 num_entries = MAX_LOOKUP_SIDS;
978                 DEBUG(5,("_lsa_lookup_names: truncating name lookup list to %d\n", num_entries));
979         }
980                 
981         /* Probably the lookup_level is some sort of bitmask. */
982         if (q_u->lookup_level == 1) {
983                 flags = LOOKUP_NAME_ALL;
984         }
985
986         ref = TALLOC_ZERO_P(p->mem_ctx, DOM_R_REF);
987         rids = TALLOC_ZERO_ARRAY(p->mem_ctx, DOM_RID, num_entries);
988         rids2 = TALLOC_ZERO_ARRAY(p->mem_ctx, DOM_RID2, num_entries);
989
990         if (!find_policy_by_hnd(p, &q_u->pol, (void **)(void *)&handle)) {
991                 r_u->status = NT_STATUS_INVALID_HANDLE;
992                 goto done;
993         }
994
995         /* check if the user have enough rights */
996         if (!(handle->access & POLICY_LOOKUP_NAMES)) {
997                 r_u->status = NT_STATUS_ACCESS_DENIED;
998                 goto done;
999         }
1000
1001         if (!ref || !rids || !rids2)
1002                 return NT_STATUS_NO_MEMORY;
1003
1004         /* set up the LSA Lookup RIDs response */
1005         mapped_count = init_lsa_rids(p->mem_ctx, ref, rids, num_entries,
1006                                       names, flags);
1007 done:
1008
1009         if (NT_STATUS_IS_OK(r_u->status)) {
1010                 if (mapped_count == 0)
1011                         r_u->status = NT_STATUS_NONE_MAPPED;
1012                 else if (mapped_count != num_entries)
1013                         r_u->status = STATUS_SOME_UNMAPPED;
1014         }
1015
1016         /* Convert the rids array to rids2. */
1017         for (i = 0; i < num_entries; i++) {
1018                 rids2[i].type = rids[i].type;
1019                 rids2[i].rid = rids[i].rid;
1020                 rids2[i].rid_idx = rids[i].rid_idx;
1021                 rids2[i].unknown = 0;
1022         }
1023
1024         init_reply_lookup_names2(r_u, ref, num_entries, rids2, mapped_count);
1025
1026         return r_u->status;
1027 }
1028
1029 /***************************************************************************
1030 lsa_reply_lookup_names3 - stub for now.
1031  ***************************************************************************/
1032
1033 NTSTATUS _lsa_lookup_names3(pipes_struct *p, LSA_Q_LOOKUP_NAMES3 *q_u, LSA_R_LOOKUP_NAMES3 *r_u)
1034 {
1035         return NT_STATUS_ACCESS_DENIED;
1036 }
1037
1038 /***************************************************************************
1039 lsa_reply_lookup_names4 - stub for now.
1040  ***************************************************************************/
1041
1042 NTSTATUS _lsa_lookup_names4(pipes_struct *p, LSA_Q_LOOKUP_NAMES4 *q_u, LSA_R_LOOKUP_NAMES4 *r_u)
1043 {
1044         return NT_STATUS_ACCESS_DENIED;
1045 }
1046
1047 /***************************************************************************
1048  _lsa_close. Also weird - needs to check if lsa handle is correct. JRA.
1049  ***************************************************************************/
1050
1051 NTSTATUS _lsa_close(pipes_struct *p, LSA_Q_CLOSE *q_u, LSA_R_CLOSE *r_u)
1052 {
1053         if (!find_policy_by_hnd(p, &q_u->pol, NULL))
1054                 return NT_STATUS_INVALID_HANDLE;
1055
1056         close_policy_hnd(p, &q_u->pol);
1057         return NT_STATUS_OK;
1058 }
1059
1060 /***************************************************************************
1061  ***************************************************************************/
1062
1063 NTSTATUS _lsa_open_secret(pipes_struct *p, LSA_Q_OPEN_SECRET *q_u, LSA_R_OPEN_SECRET *r_u)
1064 {
1065         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1066 }
1067
1068 /***************************************************************************
1069  ***************************************************************************/
1070
1071 NTSTATUS _lsa_open_trusted_domain(pipes_struct *p, LSA_Q_OPEN_TRUSTED_DOMAIN *q_u, LSA_R_OPEN_TRUSTED_DOMAIN *r_u)
1072 {
1073         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1074 }
1075
1076 /***************************************************************************
1077  ***************************************************************************/
1078
1079 NTSTATUS _lsa_create_trusted_domain(pipes_struct *p, LSA_Q_CREATE_TRUSTED_DOMAIN *q_u, LSA_R_CREATE_TRUSTED_DOMAIN *r_u)
1080 {
1081         return NT_STATUS_ACCESS_DENIED;
1082 }
1083
1084 /***************************************************************************
1085  ***************************************************************************/
1086
1087 NTSTATUS _lsa_create_secret(pipes_struct *p, LSA_Q_CREATE_SECRET *q_u, LSA_R_CREATE_SECRET *r_u)
1088 {
1089         return NT_STATUS_ACCESS_DENIED;
1090 }
1091
1092 /***************************************************************************
1093  ***************************************************************************/
1094
1095 NTSTATUS _lsa_set_secret(pipes_struct *p, LSA_Q_SET_SECRET *q_u, LSA_R_SET_SECRET *r_u)
1096 {
1097         return NT_STATUS_ACCESS_DENIED;
1098 }
1099
1100 /***************************************************************************
1101  ***************************************************************************/
1102
1103 NTSTATUS _lsa_delete_object(pipes_struct *p, LSA_Q_DELETE_OBJECT *q_u, LSA_R_DELETE_OBJECT *r_u)
1104 {
1105         return NT_STATUS_ACCESS_DENIED;
1106 }
1107
1108 /***************************************************************************
1109 _lsa_enum_privs.
1110  ***************************************************************************/
1111
1112 NTSTATUS _lsa_enum_privs(pipes_struct *p, LSA_Q_ENUM_PRIVS *q_u, LSA_R_ENUM_PRIVS *r_u)
1113 {
1114         struct lsa_info *handle;
1115         uint32 i;
1116         uint32 enum_context = q_u->enum_context;
1117         int num_privs = count_all_privileges();
1118         LSA_PRIV_ENTRY *entries = NULL;
1119         LUID_ATTR luid;
1120
1121         /* remember that the enum_context starts at 0 and not 1 */
1122
1123         if ( enum_context >= num_privs )
1124                 return NT_STATUS_NO_MORE_ENTRIES;
1125                 
1126         DEBUG(10,("_lsa_enum_privs: enum_context:%d total entries:%d\n", 
1127                 enum_context, num_privs));
1128         
1129         if (!find_policy_by_hnd(p, &q_u->pol, (void **)(void *)&handle))
1130                 return NT_STATUS_INVALID_HANDLE;
1131
1132         /* check if the user have enough rights
1133            I don't know if it's the right one. not documented.  */
1134
1135         if (!(handle->access & POLICY_VIEW_LOCAL_INFORMATION))
1136                 return NT_STATUS_ACCESS_DENIED;
1137
1138         if ( !(entries = TALLOC_ZERO_ARRAY(p->mem_ctx, LSA_PRIV_ENTRY, num_privs )) )
1139                 return NT_STATUS_NO_MEMORY;
1140
1141         for (i = 0; i < num_privs; i++) {
1142                 if( i < enum_context) {
1143                         init_unistr2(&entries[i].name, NULL, UNI_FLAGS_NONE);
1144                         init_uni_hdr(&entries[i].hdr_name, &entries[i].name);
1145                         
1146                         entries[i].luid_low = 0;
1147                         entries[i].luid_high = 0;
1148                 } else {
1149                         init_unistr2(&entries[i].name, privs[i].name, UNI_FLAGS_NONE);
1150                         init_uni_hdr(&entries[i].hdr_name, &entries[i].name);
1151                         
1152                         luid = get_privilege_luid( &privs[i].se_priv );
1153                         
1154                         entries[i].luid_low = luid.luid.low;
1155                         entries[i].luid_high = luid.luid.high;
1156                 }
1157         }
1158
1159         enum_context = num_privs;
1160         
1161         init_lsa_r_enum_privs(r_u, enum_context, num_privs, entries);
1162
1163         return NT_STATUS_OK;
1164 }
1165
1166 /***************************************************************************
1167 _lsa_priv_get_dispname.
1168  ***************************************************************************/
1169
1170 NTSTATUS _lsa_priv_get_dispname(pipes_struct *p, LSA_Q_PRIV_GET_DISPNAME *q_u, LSA_R_PRIV_GET_DISPNAME *r_u)
1171 {
1172         struct lsa_info *handle;
1173         fstring name_asc;
1174         const char *description;
1175
1176         if (!find_policy_by_hnd(p, &q_u->pol, (void **)(void *)&handle))
1177                 return NT_STATUS_INVALID_HANDLE;
1178
1179         /* check if the user have enough rights */
1180
1181         /*
1182          * I don't know if it's the right one. not documented.
1183          */
1184         if (!(handle->access & POLICY_VIEW_LOCAL_INFORMATION))
1185                 return NT_STATUS_ACCESS_DENIED;
1186
1187         unistr2_to_ascii(name_asc, &q_u->name, sizeof(name_asc));
1188
1189         DEBUG(10,("_lsa_priv_get_dispname: name = %s\n", name_asc));
1190
1191         description = get_privilege_dispname( name_asc );
1192         
1193         if ( description ) {
1194                 DEBUG(10,("_lsa_priv_get_dispname: display name = %s\n", description));
1195                 
1196                 init_unistr2(&r_u->desc, description, UNI_FLAGS_NONE);
1197                 init_uni_hdr(&r_u->hdr_desc, &r_u->desc);
1198
1199                 r_u->ptr_info = 0xdeadbeef;
1200                 r_u->lang_id = q_u->lang_id;
1201                 
1202                 return NT_STATUS_OK;
1203         } else {
1204                 DEBUG(10,("_lsa_priv_get_dispname: doesn't exist\n"));
1205                 
1206                 r_u->ptr_info = 0;
1207                 
1208                 return NT_STATUS_NO_SUCH_PRIVILEGE;
1209         }
1210 }
1211
1212 /***************************************************************************
1213 _lsa_enum_accounts.
1214  ***************************************************************************/
1215
1216 NTSTATUS _lsa_enum_accounts(pipes_struct *p, LSA_Q_ENUM_ACCOUNTS *q_u, LSA_R_ENUM_ACCOUNTS *r_u)
1217 {
1218         struct lsa_info *handle;
1219         DOM_SID *sid_list;
1220         int i, j, num_entries;
1221         LSA_SID_ENUM *sids=&r_u->sids;
1222         NTSTATUS ret;
1223
1224         if (!find_policy_by_hnd(p, &q_u->pol, (void **)(void *)&handle))
1225                 return NT_STATUS_INVALID_HANDLE;
1226
1227         if (!(handle->access & POLICY_VIEW_LOCAL_INFORMATION))
1228                 return NT_STATUS_ACCESS_DENIED;
1229
1230         sid_list = NULL;
1231         num_entries = 0;
1232
1233         /* The only way we can currently find out all the SIDs that have been
1234            privileged is to scan all privileges */
1235
1236         if (!NT_STATUS_IS_OK(ret = privilege_enumerate_accounts(&sid_list, &num_entries))) {
1237                 return ret;
1238         }
1239
1240         if (q_u->enum_context >= num_entries)
1241                 return NT_STATUS_NO_MORE_ENTRIES;
1242
1243         sids->ptr_sid = TALLOC_ZERO_ARRAY(p->mem_ctx, uint32, num_entries-q_u->enum_context);
1244         sids->sid = TALLOC_ZERO_ARRAY(p->mem_ctx, DOM_SID2, num_entries-q_u->enum_context);
1245
1246         if (sids->ptr_sid==NULL || sids->sid==NULL) {
1247                 SAFE_FREE(sid_list);
1248                 return NT_STATUS_NO_MEMORY;
1249         }
1250
1251         for (i = q_u->enum_context, j = 0; i < num_entries; i++, j++) {
1252                 init_dom_sid2(&(*sids).sid[j], &sid_list[i]);
1253                 (*sids).ptr_sid[j] = 1;
1254         }
1255
1256         SAFE_FREE(sid_list);
1257
1258         init_lsa_r_enum_accounts(r_u, num_entries);
1259
1260         return NT_STATUS_OK;
1261 }
1262
1263
1264 NTSTATUS _lsa_unk_get_connuser(pipes_struct *p, LSA_Q_UNK_GET_CONNUSER *q_u, LSA_R_UNK_GET_CONNUSER *r_u)
1265 {
1266         fstring username, domname;
1267         user_struct *vuser = get_valid_user_struct(p->vuid);
1268   
1269         if (vuser == NULL)
1270                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1271   
1272         fstrcpy(username, vuser->user.smb_name);
1273         fstrcpy(domname, vuser->user.domain);
1274   
1275         r_u->ptr_user_name = 1;
1276         init_unistr2(&r_u->uni2_user_name, username, UNI_STR_TERMINATE);
1277         init_uni_hdr(&r_u->hdr_user_name, &r_u->uni2_user_name);
1278
1279         r_u->unk1 = 1;
1280   
1281         r_u->ptr_dom_name = 1;
1282         init_unistr2(&r_u->uni2_dom_name, domname,  UNI_STR_TERMINATE);
1283         init_uni_hdr(&r_u->hdr_dom_name, &r_u->uni2_dom_name);
1284
1285         r_u->status = NT_STATUS_OK;
1286   
1287         return r_u->status;
1288 }
1289
1290 /***************************************************************************
1291  Lsa Create Account 
1292  ***************************************************************************/
1293
1294 NTSTATUS _lsa_create_account(pipes_struct *p, LSA_Q_CREATEACCOUNT *q_u, LSA_R_CREATEACCOUNT *r_u)
1295 {
1296         struct lsa_info *handle;
1297         struct lsa_info *info;
1298
1299         /* find the connection policy handle. */
1300         if (!find_policy_by_hnd(p, &q_u->pol, (void **)(void *)&handle))
1301                 return NT_STATUS_INVALID_HANDLE;
1302
1303         /* check if the user have enough rights */
1304
1305         /*
1306          * I don't know if it's the right one. not documented.
1307          * but guessed with rpcclient.
1308          */
1309         if (!(handle->access & POLICY_GET_PRIVATE_INFORMATION))
1310                 return NT_STATUS_ACCESS_DENIED;
1311
1312         /* check to see if the pipe_user is a Domain Admin since 
1313            account_pol.tdb was already opened as root, this is all we have */
1314            
1315         if ( !nt_token_check_domain_rid( p->pipe_user.nt_user_token, DOMAIN_GROUP_RID_ADMINS ) )
1316                 return NT_STATUS_ACCESS_DENIED;
1317                 
1318         if ( is_privileged_sid( &q_u->sid.sid ) )
1319                 return NT_STATUS_OBJECT_NAME_COLLISION;
1320
1321         /* associate the user/group SID with the (unique) handle. */
1322         
1323         if ((info = SMB_MALLOC_P(struct lsa_info)) == NULL)
1324                 return NT_STATUS_NO_MEMORY;
1325
1326         ZERO_STRUCTP(info);
1327         info->sid = q_u->sid.sid;
1328         info->access = q_u->access;
1329
1330         /* get a (unique) handle.  open a policy on it. */
1331         if (!create_policy_hnd(p, &r_u->pol, free_lsa_info, (void *)info))
1332                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1333
1334         return privilege_create_account( &info->sid );
1335 }
1336
1337
1338 /***************************************************************************
1339  Lsa Open Account
1340  ***************************************************************************/
1341
1342 NTSTATUS _lsa_open_account(pipes_struct *p, LSA_Q_OPENACCOUNT *q_u, LSA_R_OPENACCOUNT *r_u)
1343 {
1344         struct lsa_info *handle;
1345         struct lsa_info *info;
1346
1347         /* find the connection policy handle. */
1348         if (!find_policy_by_hnd(p, &q_u->pol, (void **)(void *)&handle))
1349                 return NT_STATUS_INVALID_HANDLE;
1350
1351         /* check if the user have enough rights */
1352
1353         /*
1354          * I don't know if it's the right one. not documented.
1355          * but guessed with rpcclient.
1356          */
1357         if (!(handle->access & POLICY_GET_PRIVATE_INFORMATION))
1358                 return NT_STATUS_ACCESS_DENIED;
1359
1360         /* TODO: Fis the parsing routine before reenabling this check! */
1361         #if 0
1362         if (!lookup_sid(&handle->sid, dom_name, name, &type))
1363                 return NT_STATUS_ACCESS_DENIED;
1364         #endif
1365         /* associate the user/group SID with the (unique) handle. */
1366         if ((info = SMB_MALLOC_P(struct lsa_info)) == NULL)
1367                 return NT_STATUS_NO_MEMORY;
1368
1369         ZERO_STRUCTP(info);
1370         info->sid = q_u->sid.sid;
1371         info->access = q_u->access;
1372
1373         /* get a (unique) handle.  open a policy on it. */
1374         if (!create_policy_hnd(p, &r_u->pol, free_lsa_info, (void *)info))
1375                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1376
1377         return NT_STATUS_OK;
1378 }
1379
1380 /***************************************************************************
1381  For a given SID, enumerate all the privilege this account has.
1382  ***************************************************************************/
1383
1384 NTSTATUS _lsa_enum_privsaccount(pipes_struct *p, prs_struct *ps, LSA_Q_ENUMPRIVSACCOUNT *q_u, LSA_R_ENUMPRIVSACCOUNT *r_u)
1385 {
1386         struct lsa_info *info=NULL;
1387         SE_PRIV mask;
1388         PRIVILEGE_SET privileges;
1389
1390         /* find the connection policy handle. */
1391         if (!find_policy_by_hnd(p, &q_u->pol, (void **)(void *)&info))
1392                 return NT_STATUS_INVALID_HANDLE;
1393
1394         if ( !get_privileges_for_sids( &mask, &info->sid, 1 ) ) 
1395                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1396
1397         privilege_set_init( &privileges );
1398
1399         if ( se_priv_to_privilege_set( &privileges, &mask ) ) {
1400
1401                 DEBUG(10,("_lsa_enum_privsaccount: %s has %d privileges\n", 
1402                         sid_string_static(&info->sid), privileges.count));
1403
1404                 r_u->status = init_lsa_r_enum_privsaccount(ps->mem_ctx, r_u, privileges.set, privileges.count, 0);
1405         }
1406         else
1407                 r_u->status = NT_STATUS_NO_SUCH_PRIVILEGE;
1408
1409         privilege_set_free( &privileges );
1410
1411         return r_u->status;
1412 }
1413
1414 /***************************************************************************
1415  
1416  ***************************************************************************/
1417
1418 NTSTATUS _lsa_getsystemaccount(pipes_struct *p, LSA_Q_GETSYSTEMACCOUNT *q_u, LSA_R_GETSYSTEMACCOUNT *r_u)
1419 {
1420         struct lsa_info *info=NULL;
1421
1422         /* find the connection policy handle. */
1423
1424         if (!find_policy_by_hnd(p, &q_u->pol, (void **)(void *)&info))
1425                 return NT_STATUS_INVALID_HANDLE;
1426
1427         if (!lookup_sid(p->mem_ctx, &info->sid, NULL, NULL, NULL))
1428                 return NT_STATUS_ACCESS_DENIED;
1429
1430         /*
1431           0x01 -> Log on locally
1432           0x02 -> Access this computer from network
1433           0x04 -> Log on as a batch job
1434           0x10 -> Log on as a service
1435           
1436           they can be ORed together
1437         */
1438
1439         r_u->access = PR_LOG_ON_LOCALLY | PR_ACCESS_FROM_NETWORK;
1440
1441         return NT_STATUS_OK;
1442 }
1443
1444 /***************************************************************************
1445   update the systemaccount information
1446  ***************************************************************************/
1447
1448 NTSTATUS _lsa_setsystemaccount(pipes_struct *p, LSA_Q_SETSYSTEMACCOUNT *q_u, LSA_R_SETSYSTEMACCOUNT *r_u)
1449 {
1450         struct lsa_info *info=NULL;
1451         GROUP_MAP map;
1452         r_u->status = NT_STATUS_OK;
1453
1454         /* find the connection policy handle. */
1455         if (!find_policy_by_hnd(p, &q_u->pol, (void **)(void *)&info))
1456                 return NT_STATUS_INVALID_HANDLE;
1457
1458         /* check to see if the pipe_user is a Domain Admin since 
1459            account_pol.tdb was already opened as root, this is all we have */
1460            
1461         if ( !nt_token_check_domain_rid( p->pipe_user.nt_user_token, DOMAIN_GROUP_RID_ADMINS ) )
1462                 return NT_STATUS_ACCESS_DENIED;
1463
1464         if (!pdb_getgrsid(&map, info->sid))
1465                 return NT_STATUS_NO_SUCH_GROUP;
1466
1467         return pdb_update_group_mapping_entry(&map);
1468 }
1469
1470 /***************************************************************************
1471  For a given SID, add some privileges.
1472  ***************************************************************************/
1473
1474 NTSTATUS _lsa_addprivs(pipes_struct *p, LSA_Q_ADDPRIVS *q_u, LSA_R_ADDPRIVS *r_u)
1475 {
1476         struct lsa_info *info = NULL;
1477         SE_PRIV mask;
1478         PRIVILEGE_SET *set = NULL;
1479         struct current_user user;
1480
1481         /* find the connection policy handle. */
1482         if (!find_policy_by_hnd(p, &q_u->pol, (void **)(void *)&info))
1483                 return NT_STATUS_INVALID_HANDLE;
1484                 
1485         /* check to see if the pipe_user is root or a Domain Admin since 
1486            account_pol.tdb was already opened as root, this is all we have */
1487            
1488         get_current_user( &user, p );
1489         if ( user.ut.uid != sec_initial_uid() 
1490                 && !nt_token_check_domain_rid( p->pipe_user.nt_user_token, DOMAIN_GROUP_RID_ADMINS ) )
1491         {
1492                 return NT_STATUS_ACCESS_DENIED;
1493         }
1494
1495         set = &q_u->set;
1496
1497         if ( !privilege_set_to_se_priv( &mask, set ) )
1498                 return NT_STATUS_NO_SUCH_PRIVILEGE;
1499
1500         if ( !grant_privilege( &info->sid, &mask ) ) {
1501                 DEBUG(3,("_lsa_addprivs: grant_privilege(%s) failed!\n",
1502                         sid_string_static(&info->sid) ));
1503                 DEBUG(3,("Privilege mask:\n"));
1504                 dump_se_priv( DBGC_ALL, 3, &mask );
1505                 return NT_STATUS_NO_SUCH_PRIVILEGE;
1506         }
1507
1508         return NT_STATUS_OK;
1509 }
1510
1511 /***************************************************************************
1512  For a given SID, remove some privileges.
1513  ***************************************************************************/
1514
1515 NTSTATUS _lsa_removeprivs(pipes_struct *p, LSA_Q_REMOVEPRIVS *q_u, LSA_R_REMOVEPRIVS *r_u)
1516 {
1517         struct lsa_info *info = NULL;
1518         SE_PRIV mask;
1519         PRIVILEGE_SET *set = NULL;
1520         struct current_user user;
1521
1522         /* find the connection policy handle. */
1523         if (!find_policy_by_hnd(p, &q_u->pol, (void **)(void *)&info))
1524                 return NT_STATUS_INVALID_HANDLE;
1525
1526         /* check to see if the pipe_user is root or a Domain Admin since 
1527            account_pol.tdb was already opened as root, this is all we have */
1528            
1529         get_current_user( &user, p );
1530         if ( user.ut.uid != sec_initial_uid()
1531                 && !nt_token_check_domain_rid( p->pipe_user.nt_user_token, DOMAIN_GROUP_RID_ADMINS ) ) 
1532         {
1533                 return NT_STATUS_ACCESS_DENIED;
1534         }
1535
1536         set = &q_u->set;
1537
1538         if ( !privilege_set_to_se_priv( &mask, set ) )
1539                 return NT_STATUS_NO_SUCH_PRIVILEGE;
1540
1541         if ( !revoke_privilege( &info->sid, &mask ) ) {
1542                 DEBUG(3,("_lsa_removeprivs: revoke_privilege(%s) failed!\n",
1543                         sid_string_static(&info->sid) ));
1544                 DEBUG(3,("Privilege mask:\n"));
1545                 dump_se_priv( DBGC_ALL, 3, &mask );
1546                 return NT_STATUS_NO_SUCH_PRIVILEGE;
1547         }
1548
1549         return NT_STATUS_OK;
1550 }
1551
1552 /***************************************************************************
1553  For a given SID, remove some privileges.
1554  ***************************************************************************/
1555
1556 NTSTATUS _lsa_query_secobj(pipes_struct *p, LSA_Q_QUERY_SEC_OBJ *q_u, LSA_R_QUERY_SEC_OBJ *r_u)
1557 {
1558         struct lsa_info *handle=NULL;
1559         SEC_DESC *psd = NULL;
1560         size_t sd_size;
1561         NTSTATUS status;
1562
1563         r_u->status = NT_STATUS_OK;
1564
1565         /* find the connection policy handle. */
1566         if (!find_policy_by_hnd(p, &q_u->pol, (void **)(void *)&handle))
1567                 return NT_STATUS_INVALID_HANDLE;
1568
1569         /* check if the user have enough rights */
1570         if (!(handle->access & POLICY_VIEW_LOCAL_INFORMATION))
1571                 return NT_STATUS_ACCESS_DENIED;
1572
1573
1574         switch (q_u->sec_info) {
1575         case 1:
1576                 /* SD contains only the owner */
1577
1578                 status=lsa_get_generic_sd(p->mem_ctx, &psd, &sd_size);
1579                 if(!NT_STATUS_IS_OK(status))
1580                         return NT_STATUS_NO_MEMORY;
1581
1582
1583                 if((r_u->buf = make_sec_desc_buf(p->mem_ctx, sd_size, psd)) == NULL)
1584                         return NT_STATUS_NO_MEMORY;
1585                 break;
1586         case 4:
1587                 /* SD contains only the ACL */
1588
1589                 status=lsa_get_generic_sd(p->mem_ctx, &psd, &sd_size);
1590                 if(!NT_STATUS_IS_OK(status))
1591                         return NT_STATUS_NO_MEMORY;
1592
1593                 if((r_u->buf = make_sec_desc_buf(p->mem_ctx, sd_size, psd)) == NULL)
1594                         return NT_STATUS_NO_MEMORY;
1595                 break;
1596         default:
1597                 return NT_STATUS_INVALID_LEVEL;
1598         }
1599
1600         r_u->ptr=1;
1601
1602         return r_u->status;
1603 }
1604
1605 #if 0   /* AD DC work in ongoing in Samba 4 */
1606
1607 /***************************************************************************
1608  ***************************************************************************/
1609
1610 NTSTATUS _lsa_query_info2(pipes_struct *p, LSA_Q_QUERY_INFO2 *q_u, LSA_R_QUERY_INFO2 *r_u)
1611 {
1612         struct lsa_info *handle;
1613         const char *nb_name;
1614         char *dns_name = NULL;
1615         char *forest_name = NULL;
1616         DOM_SID *sid = NULL;
1617         struct uuid guid;
1618         fstring dnsdomname;
1619
1620         ZERO_STRUCT(guid);
1621         r_u->status = NT_STATUS_OK;
1622
1623         if (!find_policy_by_hnd(p, &q_u->pol, (void **)(void *)&handle))
1624                 return NT_STATUS_INVALID_HANDLE;
1625
1626         switch (q_u->info_class) {
1627         case 0x0c:
1628                 /* check if the user have enough rights */
1629                 if (!(handle->access & POLICY_VIEW_LOCAL_INFORMATION))
1630                         return NT_STATUS_ACCESS_DENIED;
1631
1632                 /* Request PolicyPrimaryDomainInformation. */
1633                 switch (lp_server_role()) {
1634                         case ROLE_DOMAIN_PDC:
1635                         case ROLE_DOMAIN_BDC:
1636                                 nb_name = get_global_sam_name();
1637                                 /* ugly temp hack for these next two */
1638
1639                                 /* This should be a 'netbios domain -> DNS domain' mapping */
1640                                 dnsdomname[0] = '\0';
1641                                 get_mydnsdomname(dnsdomname);
1642                                 strlower_m(dnsdomname);
1643                                 
1644                                 dns_name = dnsdomname;
1645                                 forest_name = dnsdomname;
1646
1647                                 sid = get_global_sam_sid();
1648                                 secrets_fetch_domain_guid(lp_workgroup(), &guid);
1649                                 break;
1650                         default:
1651                                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1652                 }
1653                 init_dns_dom_info(&r_u->info.dns_dom_info, nb_name, dns_name, 
1654                                   forest_name,&guid,sid);
1655                 break;
1656         default:
1657                 DEBUG(0,("_lsa_query_info2: unknown info level in Lsa Query: %d\n", q_u->info_class));
1658                 r_u->status = NT_STATUS_INVALID_INFO_CLASS;
1659                 break;
1660         }
1661
1662         if (NT_STATUS_IS_OK(r_u->status)) {
1663                 r_u->ptr = 0x1;
1664                 r_u->info_class = q_u->info_class;
1665         }
1666
1667         return r_u->status;
1668 }
1669 #endif  /* AD DC work in ongoing in Samba 4 */
1670
1671 /***************************************************************************
1672  ***************************************************************************/
1673
1674 NTSTATUS _lsa_add_acct_rights(pipes_struct *p, LSA_Q_ADD_ACCT_RIGHTS *q_u, LSA_R_ADD_ACCT_RIGHTS *r_u)
1675 {
1676         struct lsa_info *info = NULL;
1677         int i = 0;
1678         DOM_SID sid;
1679         fstring privname;
1680         UNISTR4_ARRAY *uni_privnames = q_u->rights;
1681         struct current_user user;
1682         
1683
1684         /* find the connection policy handle. */
1685         if (!find_policy_by_hnd(p, &q_u->pol, (void **)(void *)&info))
1686                 return NT_STATUS_INVALID_HANDLE;
1687                 
1688         /* check to see if the pipe_user is a Domain Admin since 
1689            account_pol.tdb was already opened as root, this is all we have */
1690            
1691         get_current_user( &user, p );
1692         if ( user.ut.uid != sec_initial_uid()
1693                 && !nt_token_check_domain_rid( p->pipe_user.nt_user_token, DOMAIN_GROUP_RID_ADMINS ) ) 
1694         {
1695                 return NT_STATUS_ACCESS_DENIED;
1696         }
1697
1698         /* according to an NT4 PDC, you can add privileges to SIDs even without
1699            call_lsa_create_account() first.  And you can use any arbitrary SID. */
1700            
1701         sid_copy( &sid, &q_u->sid.sid );
1702         
1703         /* just a little sanity check */
1704         
1705         if ( q_u->count != uni_privnames->count ) {
1706                 DEBUG(0,("_lsa_add_acct_rights: count != number of UNISTR2 elements!\n"));
1707                 return NT_STATUS_INVALID_HANDLE;        
1708         }
1709                 
1710         for ( i=0; i<q_u->count; i++ ) {
1711                 UNISTR4 *uni4_str = &uni_privnames->strings[i];
1712
1713                 /* only try to add non-null strings */
1714
1715                 if ( !uni4_str->string )
1716                         continue;
1717
1718                 rpcstr_pull( privname, uni4_str->string->buffer, sizeof(privname), -1, STR_TERMINATE );
1719                 
1720                 if ( !grant_privilege_by_name( &sid, privname ) ) {
1721                         DEBUG(2,("_lsa_add_acct_rights: Failed to add privilege [%s]\n", privname ));
1722                         return NT_STATUS_NO_SUCH_PRIVILEGE;
1723                 }
1724         }
1725
1726         return NT_STATUS_OK;
1727 }
1728
1729 /***************************************************************************
1730  ***************************************************************************/
1731
1732 NTSTATUS _lsa_remove_acct_rights(pipes_struct *p, LSA_Q_REMOVE_ACCT_RIGHTS *q_u, LSA_R_REMOVE_ACCT_RIGHTS *r_u)
1733 {
1734         struct lsa_info *info = NULL;
1735         int i = 0;
1736         DOM_SID sid;
1737         fstring privname;
1738         UNISTR4_ARRAY *uni_privnames = q_u->rights;
1739         struct current_user user;
1740         
1741
1742         /* find the connection policy handle. */
1743         if (!find_policy_by_hnd(p, &q_u->pol, (void **)(void *)&info))
1744                 return NT_STATUS_INVALID_HANDLE;
1745                 
1746         /* check to see if the pipe_user is a Domain Admin since 
1747            account_pol.tdb was already opened as root, this is all we have */
1748            
1749         get_current_user( &user, p );
1750         if ( user.ut.uid != sec_initial_uid()
1751                 && !nt_token_check_domain_rid( p->pipe_user.nt_user_token, DOMAIN_GROUP_RID_ADMINS ) )
1752         {
1753                 return NT_STATUS_ACCESS_DENIED;
1754         }
1755
1756         sid_copy( &sid, &q_u->sid.sid );
1757
1758         if ( q_u->removeall ) {
1759                 if ( !revoke_all_privileges( &sid ) ) 
1760                         return NT_STATUS_ACCESS_DENIED;
1761         
1762                 return NT_STATUS_OK;
1763         }
1764         
1765         /* just a little sanity check */
1766         
1767         if ( q_u->count != uni_privnames->count ) {
1768                 DEBUG(0,("_lsa_add_acct_rights: count != number of UNISTR2 elements!\n"));
1769                 return NT_STATUS_INVALID_HANDLE;        
1770         }
1771                 
1772         for ( i=0; i<q_u->count; i++ ) {
1773                 UNISTR4 *uni4_str = &uni_privnames->strings[i];
1774
1775                 /* only try to add non-null strings */
1776
1777                 if ( !uni4_str->string )
1778                         continue;
1779
1780                 rpcstr_pull( privname, uni4_str->string->buffer, sizeof(privname), -1, STR_TERMINATE );
1781                 
1782                 if ( !revoke_privilege_by_name( &sid, privname ) ) {
1783                         DEBUG(2,("_lsa_remove_acct_rights: Failed to revoke privilege [%s]\n", privname ));
1784                         return NT_STATUS_NO_SUCH_PRIVILEGE;
1785                 }
1786         }
1787
1788         return NT_STATUS_OK;
1789 }
1790
1791
1792 /***************************************************************************
1793  ***************************************************************************/
1794
1795 NTSTATUS _lsa_enum_acct_rights(pipes_struct *p, LSA_Q_ENUM_ACCT_RIGHTS *q_u, LSA_R_ENUM_ACCT_RIGHTS *r_u)
1796 {
1797         struct lsa_info *info = NULL;
1798         DOM_SID sid;
1799         PRIVILEGE_SET privileges;
1800         SE_PRIV mask;
1801         
1802
1803         /* find the connection policy handle. */
1804         
1805         if (!find_policy_by_hnd(p, &q_u->pol, (void **)(void *)&info))
1806                 return NT_STATUS_INVALID_HANDLE;
1807                 
1808         /* according to an NT4 PDC, you can add privileges to SIDs even without
1809            call_lsa_create_account() first.  And you can use any arbitrary SID. */
1810            
1811         sid_copy( &sid, &q_u->sid.sid );
1812         
1813         if ( !get_privileges_for_sids( &mask, &sid, 1 ) )
1814                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1815
1816         privilege_set_init( &privileges );
1817
1818         if ( se_priv_to_privilege_set( &privileges, &mask ) ) {
1819
1820                 DEBUG(10,("_lsa_enum_acct_rights: %s has %d privileges\n", 
1821                         sid_string_static(&sid), privileges.count));
1822
1823                 r_u->status = init_r_enum_acct_rights( r_u, &privileges );
1824         }
1825         else 
1826                 r_u->status = NT_STATUS_NO_SUCH_PRIVILEGE;
1827
1828         privilege_set_free( &privileges );
1829
1830         return r_u->status;
1831 }
1832
1833
1834 /***************************************************************************
1835  ***************************************************************************/
1836
1837 NTSTATUS _lsa_lookup_priv_value(pipes_struct *p, LSA_Q_LOOKUP_PRIV_VALUE *q_u, LSA_R_LOOKUP_PRIV_VALUE *r_u)
1838 {
1839         struct lsa_info *info = NULL;
1840         fstring name;
1841         LUID_ATTR priv_luid;
1842         SE_PRIV mask;
1843         
1844         /* find the connection policy handle. */
1845         
1846         if (!find_policy_by_hnd(p, &q_u->pol, (void **)(void *)&info))
1847                 return NT_STATUS_INVALID_HANDLE;
1848                 
1849         unistr2_to_ascii(name, &q_u->privname.unistring, sizeof(name));
1850         
1851         DEBUG(10,("_lsa_lookup_priv_value: name = %s\n", name));
1852
1853         if ( !se_priv_from_name( name, &mask ) )
1854                 return NT_STATUS_NO_SUCH_PRIVILEGE;
1855
1856         priv_luid = get_privilege_luid( &mask );
1857
1858         r_u->luid.low  = priv_luid.luid.low;
1859         r_u->luid.high = priv_luid.luid.high;
1860                 
1861
1862         return NT_STATUS_OK;
1863 }