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