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