s3: Move init_lsa_ref_domain_list to lib
[Samba.git] / source3 / rpc_server / lsa / srv_lsa_nt.c
blob46f42d532083d40448d0ec7cb5595385b78b777c
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, 2006.
8 * Copyright (C) Rafal Szczesniak 2002,
9 * Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2002,
10 * Copyright (C) Simo Sorce 2003.
11 * Copyright (C) Gerald (Jerry) Carter 2005.
12 * Copyright (C) Volker Lendecke 2005.
13 * Copyright (C) Guenther Deschner 2008.
14 * Copyright (C) Andrew Bartlett 2010.
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 3 of the License, or
19 * (at your option) any later version.
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, see <http://www.gnu.org/licenses/>.
30 /* This is the implementation of the lsa server code. */
32 #include "includes.h"
33 #include "ntdomain.h"
34 #include "../librpc/gen_ndr/srv_lsa.h"
35 #include "secrets.h"
36 #include "../librpc/gen_ndr/netlogon.h"
37 #include "rpc_client/init_lsa.h"
38 #include "../libcli/security/security.h"
39 #include "../libcli/security/dom_sid.h"
40 #include "../librpc/gen_ndr/drsblobs.h"
41 #include "../librpc/gen_ndr/ndr_drsblobs.h"
42 #include "../lib/crypto/arcfour.h"
43 #include "../libcli/security/dom_sid.h"
44 #include "../librpc/gen_ndr/ndr_security.h"
45 #include "passdb.h"
46 #include "auth.h"
47 #include "lib/privileges.h"
48 #include "rpc_server/srv_access_check.h"
49 #include "../librpc/gen_ndr/ndr_wkssvc.h"
50 #include "../libcli/auth/libcli_auth.h"
51 #include "../libcli/lsarpc/util_lsarpc.h"
52 #include "lsa.h"
54 #undef DBGC_CLASS
55 #define DBGC_CLASS DBGC_RPC_SRV
57 #define MAX_LOOKUP_SIDS 0x5000 /* 20480 */
59 enum lsa_handle_type {
60 LSA_HANDLE_POLICY_TYPE = 1,
61 LSA_HANDLE_ACCOUNT_TYPE = 2,
62 LSA_HANDLE_TRUST_TYPE = 3,
63 LSA_HANDLE_SECRET_TYPE = 4};
65 struct lsa_info {
66 struct dom_sid sid;
67 const char *name;
68 uint32 access;
69 enum lsa_handle_type type;
70 struct security_descriptor *sd;
73 const struct generic_mapping lsa_account_mapping = {
74 LSA_ACCOUNT_READ,
75 LSA_ACCOUNT_WRITE,
76 LSA_ACCOUNT_EXECUTE,
77 LSA_ACCOUNT_ALL_ACCESS
80 const struct generic_mapping lsa_policy_mapping = {
81 LSA_POLICY_READ,
82 LSA_POLICY_WRITE,
83 LSA_POLICY_EXECUTE,
84 LSA_POLICY_ALL_ACCESS
87 const struct generic_mapping lsa_secret_mapping = {
88 LSA_SECRET_READ,
89 LSA_SECRET_WRITE,
90 LSA_SECRET_EXECUTE,
91 LSA_SECRET_ALL_ACCESS
94 const struct generic_mapping lsa_trusted_domain_mapping = {
95 LSA_TRUSTED_DOMAIN_READ,
96 LSA_TRUSTED_DOMAIN_WRITE,
97 LSA_TRUSTED_DOMAIN_EXECUTE,
98 LSA_TRUSTED_DOMAIN_ALL_ACCESS
101 /***************************************************************************
102 initialize a lsa_DomainInfo structure.
103 ***************************************************************************/
105 static void init_dom_query_3(struct lsa_DomainInfo *r,
106 const char *name,
107 struct dom_sid *sid)
109 init_lsa_StringLarge(&r->name, name);
110 r->sid = sid;
113 /***************************************************************************
114 initialize a lsa_DomainInfo structure.
115 ***************************************************************************/
117 static void init_dom_query_5(struct lsa_DomainInfo *r,
118 const char *name,
119 struct dom_sid *sid)
121 init_lsa_StringLarge(&r->name, name);
122 r->sid = sid;
125 /***************************************************************************
126 lookup_lsa_rids. Must be called as root for lookup_name to work.
127 ***************************************************************************/
129 static NTSTATUS lookup_lsa_rids(TALLOC_CTX *mem_ctx,
130 struct lsa_RefDomainList *ref,
131 struct lsa_TranslatedSid *prid,
132 uint32_t num_entries,
133 struct lsa_String *name,
134 int flags,
135 uint32_t *pmapped_count)
137 uint32 mapped_count, i;
139 SMB_ASSERT(num_entries <= MAX_LOOKUP_SIDS);
141 mapped_count = 0;
142 *pmapped_count = 0;
144 for (i = 0; i < num_entries; i++) {
145 struct dom_sid sid;
146 uint32 rid;
147 int dom_idx;
148 const char *full_name;
149 const char *domain;
150 enum lsa_SidType type;
152 /* Split name into domain and user component */
154 /* follow w2k8 behavior and return the builtin domain when no
155 * input has been passed in */
157 if (name[i].string) {
158 full_name = name[i].string;
159 } else {
160 full_name = "BUILTIN";
163 DEBUG(5, ("lookup_lsa_rids: looking up name %s\n", full_name));
165 if (!lookup_name(mem_ctx, full_name, flags, &domain, NULL,
166 &sid, &type)) {
167 type = SID_NAME_UNKNOWN;
170 switch (type) {
171 case SID_NAME_USER:
172 case SID_NAME_DOM_GRP:
173 case SID_NAME_DOMAIN:
174 case SID_NAME_ALIAS:
175 case SID_NAME_WKN_GRP:
176 DEBUG(5, ("init_lsa_rids: %s found\n", full_name));
177 /* Leave these unchanged */
178 break;
179 default:
180 /* Don't hand out anything but the list above */
181 DEBUG(5, ("init_lsa_rids: %s not found\n", full_name));
182 type = SID_NAME_UNKNOWN;
183 break;
186 rid = 0;
187 dom_idx = -1;
189 if (type != SID_NAME_UNKNOWN) {
190 if (type == SID_NAME_DOMAIN) {
191 rid = (uint32_t)-1;
192 } else {
193 sid_split_rid(&sid, &rid);
195 dom_idx = init_lsa_ref_domain_list(mem_ctx, ref, domain, &sid);
196 mapped_count++;
199 prid[i].sid_type = type;
200 prid[i].rid = rid;
201 prid[i].sid_index = dom_idx;
204 *pmapped_count = mapped_count;
205 return NT_STATUS_OK;
208 /***************************************************************************
209 lookup_lsa_sids. Must be called as root for lookup_name to work.
210 ***************************************************************************/
212 static NTSTATUS lookup_lsa_sids(TALLOC_CTX *mem_ctx,
213 struct lsa_RefDomainList *ref,
214 struct lsa_TranslatedSid3 *trans_sids,
215 uint32_t num_entries,
216 struct lsa_String *name,
217 int flags,
218 uint32 *pmapped_count)
220 uint32 mapped_count, i;
222 SMB_ASSERT(num_entries <= MAX_LOOKUP_SIDS);
224 mapped_count = 0;
225 *pmapped_count = 0;
227 for (i = 0; i < num_entries; i++) {
228 struct dom_sid sid;
229 uint32 rid;
230 int dom_idx;
231 const char *full_name;
232 const char *domain;
233 enum lsa_SidType type;
235 ZERO_STRUCT(sid);
237 /* Split name into domain and user component */
239 full_name = name[i].string;
240 if (full_name == NULL) {
241 return NT_STATUS_NO_MEMORY;
244 DEBUG(5, ("lookup_lsa_sids: looking up name %s\n", full_name));
246 if (!lookup_name(mem_ctx, full_name, flags, &domain, NULL,
247 &sid, &type)) {
248 type = SID_NAME_UNKNOWN;
251 switch (type) {
252 case SID_NAME_USER:
253 case SID_NAME_DOM_GRP:
254 case SID_NAME_DOMAIN:
255 case SID_NAME_ALIAS:
256 case SID_NAME_WKN_GRP:
257 DEBUG(5, ("lookup_lsa_sids: %s found\n", full_name));
258 /* Leave these unchanged */
259 break;
260 default:
261 /* Don't hand out anything but the list above */
262 DEBUG(5, ("lookup_lsa_sids: %s not found\n", full_name));
263 type = SID_NAME_UNKNOWN;
264 break;
267 rid = 0;
268 dom_idx = -1;
270 if (type != SID_NAME_UNKNOWN) {
271 struct dom_sid domain_sid;
272 sid_copy(&domain_sid, &sid);
273 sid_split_rid(&domain_sid, &rid);
274 dom_idx = init_lsa_ref_domain_list(mem_ctx, ref, domain, &domain_sid);
275 mapped_count++;
278 /* Initialize the lsa_TranslatedSid3 return. */
279 trans_sids[i].sid_type = type;
280 trans_sids[i].sid = dom_sid_dup(mem_ctx, &sid);
281 trans_sids[i].sid_index = dom_idx;
284 *pmapped_count = mapped_count;
285 return NT_STATUS_OK;
288 static NTSTATUS make_lsa_object_sd(TALLOC_CTX *mem_ctx, struct security_descriptor **sd, size_t *sd_size,
289 const struct generic_mapping *map,
290 struct dom_sid *sid, uint32_t sid_access)
292 struct dom_sid adm_sid;
293 struct security_ace ace[5];
294 size_t i = 0;
296 struct security_acl *psa = NULL;
298 /* READ|EXECUTE access for Everyone */
300 init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
301 map->generic_execute | map->generic_read, 0);
303 /* Add Full Access 'BUILTIN\Administrators' and 'BUILTIN\Account Operators */
305 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
306 SEC_ACE_TYPE_ACCESS_ALLOWED, map->generic_all, 0);
307 init_sec_ace(&ace[i++], &global_sid_Builtin_Account_Operators,
308 SEC_ACE_TYPE_ACCESS_ALLOWED, map->generic_all, 0);
310 /* Add Full Access for Domain Admins */
311 sid_compose(&adm_sid, get_global_sam_sid(), DOMAIN_RID_ADMINS);
312 init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
313 map->generic_all, 0);
315 /* If we have a sid, give it some special access */
317 if (sid) {
318 init_sec_ace(&ace[i++], sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
319 sid_access, 0);
322 if((psa = make_sec_acl(mem_ctx, NT4_ACL_REVISION, i, ace)) == NULL)
323 return NT_STATUS_NO_MEMORY;
325 if((*sd = make_sec_desc(mem_ctx, SECURITY_DESCRIPTOR_REVISION_1,
326 SEC_DESC_SELF_RELATIVE, &adm_sid, NULL, NULL,
327 psa, sd_size)) == NULL)
328 return NT_STATUS_NO_MEMORY;
330 return NT_STATUS_OK;
333 /***************************************************************************
334 ***************************************************************************/
336 static NTSTATUS create_lsa_policy_handle(TALLOC_CTX *mem_ctx,
337 struct pipes_struct *p,
338 enum lsa_handle_type type,
339 uint32_t acc_granted,
340 struct dom_sid *sid,
341 const char *name,
342 const struct security_descriptor *sd,
343 struct policy_handle *handle)
345 struct lsa_info *info;
347 ZERO_STRUCTP(handle);
349 info = talloc_zero(mem_ctx, struct lsa_info);
350 if (!info) {
351 return NT_STATUS_NO_MEMORY;
354 info->type = type;
355 info->access = acc_granted;
357 if (sid) {
358 sid_copy(&info->sid, sid);
361 info->name = talloc_strdup(info, name);
363 if (sd) {
364 info->sd = dup_sec_desc(info, sd);
365 if (!info->sd) {
366 talloc_free(info);
367 return NT_STATUS_NO_MEMORY;
371 if (!create_policy_hnd(p, handle, info)) {
372 talloc_free(info);
373 ZERO_STRUCTP(handle);
374 return NT_STATUS_NO_MEMORY;
377 return NT_STATUS_OK;
380 /***************************************************************************
381 _lsa_OpenPolicy2
382 ***************************************************************************/
384 NTSTATUS _lsa_OpenPolicy2(struct pipes_struct *p,
385 struct lsa_OpenPolicy2 *r)
387 struct security_descriptor *psd = NULL;
388 size_t sd_size;
389 uint32 des_access = r->in.access_mask;
390 uint32 acc_granted;
391 NTSTATUS status;
393 if (p->transport != NCACN_NP && p->transport != NCALRPC) {
394 p->fault_state = DCERPC_FAULT_ACCESS_DENIED;
395 return NT_STATUS_ACCESS_DENIED;
398 /* Work out max allowed. */
399 map_max_allowed_access(p->session_info->security_token,
400 p->session_info->unix_token,
401 &des_access);
403 /* map the generic bits to the lsa policy ones */
404 se_map_generic(&des_access, &lsa_policy_mapping);
406 /* get the generic lsa policy SD until we store it */
407 status = make_lsa_object_sd(p->mem_ctx, &psd, &sd_size, &lsa_policy_mapping,
408 NULL, 0);
409 if (!NT_STATUS_IS_OK(status)) {
410 return status;
413 status = access_check_object(psd, p->session_info->security_token,
414 SEC_PRIV_INVALID, SEC_PRIV_INVALID, 0, des_access,
415 &acc_granted, "_lsa_OpenPolicy2" );
416 if (!NT_STATUS_IS_OK(status)) {
417 return status;
420 status = create_lsa_policy_handle(p->mem_ctx, p,
421 LSA_HANDLE_POLICY_TYPE,
422 acc_granted,
423 get_global_sam_sid(),
424 NULL,
425 psd,
426 r->out.handle);
427 if (!NT_STATUS_IS_OK(status)) {
428 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
431 return NT_STATUS_OK;
434 /***************************************************************************
435 _lsa_OpenPolicy
436 ***************************************************************************/
438 NTSTATUS _lsa_OpenPolicy(struct pipes_struct *p,
439 struct lsa_OpenPolicy *r)
441 struct lsa_OpenPolicy2 o;
443 /* _lsa_OpenPolicy2 will check if this is a NCACN_NP connection */
445 o.in.system_name = NULL; /* should be ignored */
446 o.in.attr = r->in.attr;
447 o.in.access_mask = r->in.access_mask;
449 o.out.handle = r->out.handle;
451 return _lsa_OpenPolicy2(p, &o);
454 /***************************************************************************
455 _lsa_EnumTrustDom - this needs fixing to do more than return NULL ! JRA.
456 ufff, done :) mimir
457 ***************************************************************************/
459 NTSTATUS _lsa_EnumTrustDom(struct pipes_struct *p,
460 struct lsa_EnumTrustDom *r)
462 struct lsa_info *info;
463 uint32_t count;
464 struct trustdom_info **domains;
465 struct lsa_DomainInfo *entries;
466 int i;
467 NTSTATUS nt_status;
469 if (!find_policy_by_hnd(p, r->in.handle, (void **)(void *)&info))
470 return NT_STATUS_INVALID_HANDLE;
472 if (info->type != LSA_HANDLE_POLICY_TYPE) {
473 return NT_STATUS_INVALID_HANDLE;
476 /* check if the user has enough rights */
477 if (!(info->access & LSA_POLICY_VIEW_LOCAL_INFORMATION))
478 return NT_STATUS_ACCESS_DENIED;
480 become_root();
481 nt_status = pdb_enum_trusteddoms(p->mem_ctx, &count, &domains);
482 unbecome_root();
484 if (!NT_STATUS_IS_OK(nt_status)) {
485 return nt_status;
488 entries = talloc_zero_array(p->mem_ctx, struct lsa_DomainInfo, count);
489 if (!entries) {
490 return NT_STATUS_NO_MEMORY;
493 for (i=0; i<count; i++) {
494 init_lsa_StringLarge(&entries[i].name, domains[i]->name);
495 entries[i].sid = &domains[i]->sid;
498 if (*r->in.resume_handle >= count) {
499 *r->out.resume_handle = -1;
500 TALLOC_FREE(entries);
501 return NT_STATUS_NO_MORE_ENTRIES;
504 /* return the rest, limit by max_size. Note that we
505 use the w2k3 element size value of 60 */
506 r->out.domains->count = count - *r->in.resume_handle;
507 r->out.domains->count = MIN(r->out.domains->count,
508 1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_MULTIPLIER));
510 r->out.domains->domains = entries + *r->in.resume_handle;
512 if (r->out.domains->count < count - *r->in.resume_handle) {
513 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
514 return STATUS_MORE_ENTRIES;
517 /* according to MS-LSAD 3.1.4.7.8 output resume handle MUST
518 * always be larger than the previous input resume handle, in
519 * particular when hitting the last query it is vital to set the
520 * resume handle correctly to avoid infinite client loops, as
521 * seen e.g. with Windows XP SP3 when resume handle is 0 and
522 * status is NT_STATUS_OK - gd */
524 *r->out.resume_handle = (uint32_t)-1;
526 return NT_STATUS_OK;
529 #define LSA_AUDIT_NUM_CATEGORIES_NT4 7
530 #define LSA_AUDIT_NUM_CATEGORIES_WIN2K 9
531 #define LSA_AUDIT_NUM_CATEGORIES LSA_AUDIT_NUM_CATEGORIES_NT4
533 /***************************************************************************
534 _lsa_QueryInfoPolicy
535 ***************************************************************************/
537 NTSTATUS _lsa_QueryInfoPolicy(struct pipes_struct *p,
538 struct lsa_QueryInfoPolicy *r)
540 NTSTATUS status = NT_STATUS_OK;
541 struct lsa_info *handle;
542 struct dom_sid domain_sid;
543 const char *name;
544 struct dom_sid *sid = NULL;
545 union lsa_PolicyInformation *info = NULL;
546 uint32_t acc_required = 0;
548 if (!find_policy_by_hnd(p, r->in.handle, (void **)(void *)&handle))
549 return NT_STATUS_INVALID_HANDLE;
551 if (handle->type != LSA_HANDLE_POLICY_TYPE) {
552 return NT_STATUS_INVALID_HANDLE;
555 switch (r->in.level) {
556 case LSA_POLICY_INFO_AUDIT_LOG:
557 case LSA_POLICY_INFO_AUDIT_EVENTS:
558 acc_required = LSA_POLICY_VIEW_AUDIT_INFORMATION;
559 break;
560 case LSA_POLICY_INFO_DOMAIN:
561 acc_required = LSA_POLICY_VIEW_LOCAL_INFORMATION;
562 break;
563 case LSA_POLICY_INFO_PD:
564 acc_required = LSA_POLICY_GET_PRIVATE_INFORMATION;
565 break;
566 case LSA_POLICY_INFO_ACCOUNT_DOMAIN:
567 acc_required = LSA_POLICY_VIEW_LOCAL_INFORMATION;
568 break;
569 case LSA_POLICY_INFO_ROLE:
570 case LSA_POLICY_INFO_REPLICA:
571 acc_required = LSA_POLICY_VIEW_LOCAL_INFORMATION;
572 break;
573 case LSA_POLICY_INFO_QUOTA:
574 acc_required = LSA_POLICY_VIEW_LOCAL_INFORMATION;
575 break;
576 case LSA_POLICY_INFO_MOD:
577 case LSA_POLICY_INFO_AUDIT_FULL_SET:
578 /* according to MS-LSAD 3.1.4.4.3 */
579 return NT_STATUS_INVALID_PARAMETER;
580 case LSA_POLICY_INFO_AUDIT_FULL_QUERY:
581 acc_required = LSA_POLICY_VIEW_AUDIT_INFORMATION;
582 break;
583 case LSA_POLICY_INFO_DNS:
584 case LSA_POLICY_INFO_DNS_INT:
585 case LSA_POLICY_INFO_L_ACCOUNT_DOMAIN:
586 acc_required = LSA_POLICY_VIEW_LOCAL_INFORMATION;
587 break;
588 default:
589 break;
592 if (!(handle->access & acc_required)) {
593 /* return NT_STATUS_ACCESS_DENIED; */
596 info = talloc_zero(p->mem_ctx, union lsa_PolicyInformation);
597 if (!info) {
598 return NT_STATUS_NO_MEMORY;
601 switch (r->in.level) {
602 /* according to MS-LSAD 3.1.4.4.3 */
603 case LSA_POLICY_INFO_MOD:
604 case LSA_POLICY_INFO_AUDIT_FULL_SET:
605 case LSA_POLICY_INFO_AUDIT_FULL_QUERY:
606 return NT_STATUS_INVALID_PARAMETER;
607 case LSA_POLICY_INFO_AUDIT_LOG:
608 info->audit_log.percent_full = 0;
609 info->audit_log.maximum_log_size = 0;
610 info->audit_log.retention_time = 0;
611 info->audit_log.shutdown_in_progress = 0;
612 info->audit_log.time_to_shutdown = 0;
613 info->audit_log.next_audit_record = 0;
614 status = NT_STATUS_OK;
615 break;
616 case LSA_POLICY_INFO_PD:
617 info->pd.name.string = NULL;
618 status = NT_STATUS_OK;
619 break;
620 case LSA_POLICY_INFO_REPLICA:
621 info->replica.source.string = NULL;
622 info->replica.account.string = NULL;
623 status = NT_STATUS_OK;
624 break;
625 case LSA_POLICY_INFO_QUOTA:
626 info->quota.paged_pool = 0;
627 info->quota.non_paged_pool = 0;
628 info->quota.min_wss = 0;
629 info->quota.max_wss = 0;
630 info->quota.pagefile = 0;
631 info->quota.unknown = 0;
632 status = NT_STATUS_OK;
633 break;
634 case LSA_POLICY_INFO_AUDIT_EVENTS:
637 uint32 policy_def = LSA_AUDIT_POLICY_ALL;
639 /* check if the user has enough rights */
640 if (!(handle->access & LSA_POLICY_VIEW_AUDIT_INFORMATION)) {
641 DEBUG(10,("_lsa_QueryInfoPolicy: insufficient access rights\n"));
642 return NT_STATUS_ACCESS_DENIED;
645 /* fake info: We audit everything. ;) */
647 info->audit_events.auditing_mode = true;
648 info->audit_events.count = LSA_AUDIT_NUM_CATEGORIES;
649 info->audit_events.settings = talloc_zero_array(p->mem_ctx,
650 enum lsa_PolicyAuditPolicy,
651 info->audit_events.count);
652 if (!info->audit_events.settings) {
653 return NT_STATUS_NO_MEMORY;
656 info->audit_events.settings[LSA_AUDIT_CATEGORY_ACCOUNT_MANAGEMENT] = policy_def;
657 info->audit_events.settings[LSA_AUDIT_CATEGORY_FILE_AND_OBJECT_ACCESS] = policy_def;
658 info->audit_events.settings[LSA_AUDIT_CATEGORY_LOGON] = policy_def;
659 info->audit_events.settings[LSA_AUDIT_CATEGORY_PROCCESS_TRACKING] = policy_def;
660 info->audit_events.settings[LSA_AUDIT_CATEGORY_SECURITY_POLICY_CHANGES] = policy_def;
661 info->audit_events.settings[LSA_AUDIT_CATEGORY_SYSTEM] = policy_def;
662 info->audit_events.settings[LSA_AUDIT_CATEGORY_USE_OF_USER_RIGHTS] = policy_def;
664 break;
666 case LSA_POLICY_INFO_DOMAIN:
667 /* check if the user has enough rights */
668 if (!(handle->access & LSA_POLICY_VIEW_LOCAL_INFORMATION))
669 return NT_STATUS_ACCESS_DENIED;
671 /* Request PolicyPrimaryDomainInformation. */
672 switch (lp_server_role()) {
673 case ROLE_DOMAIN_PDC:
674 case ROLE_DOMAIN_BDC:
675 name = get_global_sam_name();
676 sid = dom_sid_dup(p->mem_ctx, get_global_sam_sid());
677 if (!sid) {
678 return NT_STATUS_NO_MEMORY;
680 break;
681 case ROLE_DOMAIN_MEMBER:
682 name = lp_workgroup();
683 /* We need to return the Domain SID here. */
684 if (secrets_fetch_domain_sid(lp_workgroup(), &domain_sid)) {
685 sid = dom_sid_dup(p->mem_ctx, &domain_sid);
686 if (!sid) {
687 return NT_STATUS_NO_MEMORY;
689 } else {
690 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
692 break;
693 case ROLE_STANDALONE:
694 name = lp_workgroup();
695 sid = NULL;
696 break;
697 default:
698 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
700 init_dom_query_3(&info->domain, name, sid);
701 break;
702 case LSA_POLICY_INFO_ACCOUNT_DOMAIN:
703 /* check if the user has enough rights */
704 if (!(handle->access & LSA_POLICY_VIEW_LOCAL_INFORMATION))
705 return NT_STATUS_ACCESS_DENIED;
707 /* Request PolicyAccountDomainInformation. */
708 name = get_global_sam_name();
709 sid = get_global_sam_sid();
711 init_dom_query_5(&info->account_domain, name, sid);
712 break;
713 case LSA_POLICY_INFO_ROLE:
714 /* check if the user has enough rights */
715 if (!(handle->access & LSA_POLICY_VIEW_LOCAL_INFORMATION))
716 return NT_STATUS_ACCESS_DENIED;
718 switch (lp_server_role()) {
719 case ROLE_DOMAIN_BDC:
721 * only a BDC is a backup controller
722 * of the domain, it controls.
724 info->role.role = LSA_ROLE_BACKUP;
725 break;
726 default:
728 * any other role is a primary
729 * of the domain, it controls.
731 info->role.role = LSA_ROLE_PRIMARY;
732 break;
734 break;
735 case LSA_POLICY_INFO_DNS:
736 case LSA_POLICY_INFO_DNS_INT: {
737 struct pdb_domain_info *dominfo;
739 if ((pdb_capabilities() & PDB_CAP_ADS) == 0) {
740 DEBUG(10, ("Not replying to LSA_POLICY_INFO_DNS "
741 "without ADS passdb backend\n"));
742 status = NT_STATUS_INVALID_INFO_CLASS;
743 break;
746 dominfo = pdb_get_domain_info(info);
747 if (dominfo == NULL) {
748 status = NT_STATUS_NO_MEMORY;
749 break;
752 init_lsa_StringLarge(&info->dns.name,
753 dominfo->name);
754 init_lsa_StringLarge(&info->dns.dns_domain,
755 dominfo->dns_domain);
756 init_lsa_StringLarge(&info->dns.dns_forest,
757 dominfo->dns_forest);
758 info->dns.domain_guid = dominfo->guid;
759 info->dns.sid = &dominfo->sid;
760 break;
762 default:
763 DEBUG(0,("_lsa_QueryInfoPolicy: unknown info level in Lsa Query: %d\n",
764 r->in.level));
765 status = NT_STATUS_INVALID_INFO_CLASS;
766 break;
769 *r->out.info = info;
771 return status;
774 /***************************************************************************
775 _lsa_QueryInfoPolicy2
776 ***************************************************************************/
778 NTSTATUS _lsa_QueryInfoPolicy2(struct pipes_struct *p,
779 struct lsa_QueryInfoPolicy2 *r2)
781 struct lsa_QueryInfoPolicy r;
783 if ((pdb_capabilities() & PDB_CAP_ADS) == 0) {
784 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
785 return NT_STATUS_NOT_IMPLEMENTED;
788 ZERO_STRUCT(r);
789 r.in.handle = r2->in.handle;
790 r.in.level = r2->in.level;
791 r.out.info = r2->out.info;
793 return _lsa_QueryInfoPolicy(p, &r);
796 /***************************************************************************
797 _lsa_lookup_sids_internal
798 ***************************************************************************/
800 static NTSTATUS _lsa_lookup_sids_internal(struct pipes_struct *p,
801 TALLOC_CTX *mem_ctx,
802 uint16_t level, /* input */
803 int num_sids, /* input */
804 struct lsa_SidPtr *sid, /* input */
805 struct lsa_RefDomainList **pp_ref, /* input/output */
806 struct lsa_TranslatedName2 **pp_names,/* input/output */
807 uint32_t *pp_mapped_count) /* input/output */
809 NTSTATUS status;
810 int i;
811 const struct dom_sid **sids = NULL;
812 struct lsa_RefDomainList *ref = NULL;
813 uint32 mapped_count = 0;
814 struct lsa_dom_info *dom_infos = NULL;
815 struct lsa_name_info *name_infos = NULL;
816 struct lsa_TranslatedName2 *names = NULL;
818 *pp_mapped_count = 0;
819 *pp_names = NULL;
820 *pp_ref = NULL;
822 if (num_sids == 0) {
823 return NT_STATUS_OK;
826 sids = talloc_array(p->mem_ctx, const struct dom_sid *, num_sids);
827 ref = talloc_zero(p->mem_ctx, struct lsa_RefDomainList);
829 if (sids == NULL || ref == NULL) {
830 return NT_STATUS_NO_MEMORY;
833 for (i=0; i<num_sids; i++) {
834 sids[i] = sid[i].sid;
837 status = lookup_sids(p->mem_ctx, num_sids, sids, level,
838 &dom_infos, &name_infos);
840 if (!NT_STATUS_IS_OK(status)) {
841 return status;
844 names = talloc_array(p->mem_ctx, struct lsa_TranslatedName2, num_sids);
845 if (names == NULL) {
846 return NT_STATUS_NO_MEMORY;
849 for (i=0; i<LSA_REF_DOMAIN_LIST_MULTIPLIER; i++) {
851 if (!dom_infos[i].valid) {
852 break;
855 if (init_lsa_ref_domain_list(mem_ctx, ref,
856 dom_infos[i].name,
857 &dom_infos[i].sid) != i) {
858 DEBUG(0, ("Domain %s mentioned twice??\n",
859 dom_infos[i].name));
860 return NT_STATUS_INTERNAL_ERROR;
864 for (i=0; i<num_sids; i++) {
865 struct lsa_name_info *name = &name_infos[i];
867 if (name->type == SID_NAME_UNKNOWN) {
868 name->dom_idx = -1;
869 /* Unknown sids should return the string
870 * representation of the SID. Windows 2003 behaves
871 * rather erratic here, in many cases it returns the
872 * RID as 8 bytes hex, in others it returns the full
873 * SID. We (Jerry/VL) could not figure out which the
874 * hard cases are, so leave it with the SID. */
875 name->name = dom_sid_string(p->mem_ctx, sids[i]);
876 if (name->name == NULL) {
877 return NT_STATUS_NO_MEMORY;
879 } else {
880 mapped_count += 1;
883 names[i].sid_type = name->type;
884 names[i].name.string = name->name;
885 names[i].sid_index = name->dom_idx;
886 names[i].unknown = 0;
889 status = NT_STATUS_NONE_MAPPED;
890 if (mapped_count > 0) {
891 status = (mapped_count < num_sids) ?
892 STATUS_SOME_UNMAPPED : NT_STATUS_OK;
895 DEBUG(10, ("num_sids %d, mapped_count %d, status %s\n",
896 num_sids, mapped_count, nt_errstr(status)));
898 *pp_mapped_count = mapped_count;
899 *pp_names = names;
900 *pp_ref = ref;
902 return status;
905 /***************************************************************************
906 _lsa_LookupSids
907 ***************************************************************************/
909 NTSTATUS _lsa_LookupSids(struct pipes_struct *p,
910 struct lsa_LookupSids *r)
912 NTSTATUS status;
913 struct lsa_info *handle;
914 int num_sids = r->in.sids->num_sids;
915 uint32 mapped_count = 0;
916 struct lsa_RefDomainList *domains = NULL;
917 struct lsa_TranslatedName *names_out = NULL;
918 struct lsa_TranslatedName2 *names = NULL;
919 int i;
921 if (p->transport != NCACN_NP && p->transport != NCALRPC) {
922 p->fault_state = DCERPC_FAULT_ACCESS_DENIED;
923 return NT_STATUS_ACCESS_DENIED;
926 if ((r->in.level < 1) || (r->in.level > 6)) {
927 return NT_STATUS_INVALID_PARAMETER;
930 if (!find_policy_by_hnd(p, r->in.handle, (void **)(void *)&handle)) {
931 return NT_STATUS_INVALID_HANDLE;
934 if (handle->type != LSA_HANDLE_POLICY_TYPE) {
935 return NT_STATUS_INVALID_HANDLE;
938 /* check if the user has enough rights */
939 if (!(handle->access & LSA_POLICY_LOOKUP_NAMES)) {
940 return NT_STATUS_ACCESS_DENIED;
943 if (num_sids > MAX_LOOKUP_SIDS) {
944 DEBUG(5,("_lsa_LookupSids: limit of %d exceeded, requested %d\n",
945 MAX_LOOKUP_SIDS, num_sids));
946 return NT_STATUS_NONE_MAPPED;
949 status = _lsa_lookup_sids_internal(p,
950 p->mem_ctx,
951 r->in.level,
952 num_sids,
953 r->in.sids->sids,
954 &domains,
955 &names,
956 &mapped_count);
958 /* Only return here when there is a real error.
959 NT_STATUS_NONE_MAPPED is a special case as it indicates that none of
960 the requested sids could be resolved. Older versions of XP (pre SP3)
961 rely that we return with the string representations of those SIDs in
962 that case. If we don't, XP crashes - Guenther
965 if (NT_STATUS_IS_ERR(status) &&
966 !NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) {
967 return status;
970 /* Convert from lsa_TranslatedName2 to lsa_TranslatedName */
971 names_out = talloc_array(p->mem_ctx, struct lsa_TranslatedName,
972 num_sids);
973 if (!names_out) {
974 return NT_STATUS_NO_MEMORY;
977 for (i=0; i<num_sids; i++) {
978 names_out[i].sid_type = names[i].sid_type;
979 names_out[i].name = names[i].name;
980 names_out[i].sid_index = names[i].sid_index;
983 *r->out.domains = domains;
984 r->out.names->count = num_sids;
985 r->out.names->names = names_out;
986 *r->out.count = mapped_count;
988 return status;
991 static NTSTATUS _lsa_LookupSids_common(struct pipes_struct *p,
992 struct lsa_LookupSids2 *r)
994 NTSTATUS status;
995 struct lsa_info *handle;
996 int num_sids = r->in.sids->num_sids;
997 uint32 mapped_count = 0;
998 struct lsa_RefDomainList *domains = NULL;
999 struct lsa_TranslatedName2 *names = NULL;
1000 bool check_policy = true;
1002 switch (p->opnum) {
1003 case NDR_LSA_LOOKUPSIDS3:
1004 check_policy = false;
1005 break;
1006 case NDR_LSA_LOOKUPSIDS2:
1007 default:
1008 check_policy = true;
1011 if ((r->in.level < 1) || (r->in.level > 6)) {
1012 return NT_STATUS_INVALID_PARAMETER;
1015 if (check_policy) {
1016 if (!find_policy_by_hnd(p, r->in.handle, (void **)(void *)&handle)) {
1017 return NT_STATUS_INVALID_HANDLE;
1020 if (handle->type != LSA_HANDLE_POLICY_TYPE) {
1021 return NT_STATUS_INVALID_HANDLE;
1024 /* check if the user has enough rights */
1025 if (!(handle->access & LSA_POLICY_LOOKUP_NAMES)) {
1026 return NT_STATUS_ACCESS_DENIED;
1030 if (num_sids > MAX_LOOKUP_SIDS) {
1031 DEBUG(5,("_lsa_LookupSids2: limit of %d exceeded, requested %d\n",
1032 MAX_LOOKUP_SIDS, num_sids));
1033 return NT_STATUS_NONE_MAPPED;
1036 status = _lsa_lookup_sids_internal(p,
1037 p->mem_ctx,
1038 r->in.level,
1039 num_sids,
1040 r->in.sids->sids,
1041 &domains,
1042 &names,
1043 &mapped_count);
1045 *r->out.domains = domains;
1046 r->out.names->count = num_sids;
1047 r->out.names->names = names;
1048 *r->out.count = mapped_count;
1050 return status;
1053 /***************************************************************************
1054 _lsa_LookupSids2
1055 ***************************************************************************/
1057 NTSTATUS _lsa_LookupSids2(struct pipes_struct *p,
1058 struct lsa_LookupSids2 *r)
1060 if (p->transport != NCACN_NP && p->transport != NCALRPC) {
1061 p->fault_state = DCERPC_FAULT_ACCESS_DENIED;
1062 return NT_STATUS_ACCESS_DENIED;
1065 return _lsa_LookupSids_common(p, r);
1068 /***************************************************************************
1069 _lsa_LookupSids3
1070 ***************************************************************************/
1072 NTSTATUS _lsa_LookupSids3(struct pipes_struct *p,
1073 struct lsa_LookupSids3 *r)
1075 struct lsa_LookupSids2 q;
1077 if (p->transport != NCACN_IP_TCP) {
1078 p->fault_state = DCERPC_FAULT_ACCESS_DENIED;
1079 return NT_STATUS_ACCESS_DENIED;
1082 /* No policy handle on this call. Restrict to crypto connections. */
1083 if (p->auth.auth_type != DCERPC_AUTH_TYPE_SCHANNEL ||
1084 p->auth.auth_level < DCERPC_AUTH_LEVEL_INTEGRITY) {
1085 DEBUG(1, ("_lsa_LookupSids3: The client %s is not using "
1086 "a secure connection over netlogon\n",
1087 get_remote_machine_name() ));
1088 p->fault_state = DCERPC_FAULT_ACCESS_DENIED;
1089 return NT_STATUS_ACCESS_DENIED;
1092 q.in.handle = NULL;
1093 q.in.sids = r->in.sids;
1094 q.in.level = r->in.level;
1095 q.in.lookup_options = r->in.lookup_options;
1096 q.in.client_revision = r->in.client_revision;
1097 q.in.names = r->in.names;
1098 q.in.count = r->in.count;
1100 q.out.domains = r->out.domains;
1101 q.out.names = r->out.names;
1102 q.out.count = r->out.count;
1104 return _lsa_LookupSids_common(p, &q);
1107 /***************************************************************************
1108 ***************************************************************************/
1110 static int lsa_lookup_level_to_flags(enum lsa_LookupNamesLevel level)
1112 int flags;
1114 switch (level) {
1115 case LSA_LOOKUP_NAMES_ALL: /* 1 */
1116 flags = LOOKUP_NAME_ALL;
1117 break;
1118 case LSA_LOOKUP_NAMES_DOMAINS_ONLY: /* 2 */
1119 flags = LOOKUP_NAME_DOMAIN|LOOKUP_NAME_REMOTE|LOOKUP_NAME_ISOLATED;
1120 break;
1121 case LSA_LOOKUP_NAMES_PRIMARY_DOMAIN_ONLY: /* 3 */
1122 flags = LOOKUP_NAME_DOMAIN|LOOKUP_NAME_ISOLATED;
1123 break;
1124 case LSA_LOOKUP_NAMES_UPLEVEL_TRUSTS_ONLY: /* 4 */
1125 case LSA_LOOKUP_NAMES_FOREST_TRUSTS_ONLY: /* 5 */
1126 case LSA_LOOKUP_NAMES_UPLEVEL_TRUSTS_ONLY2: /* 6 */
1127 case LSA_LOOKUP_NAMES_RODC_REFERRAL_TO_FULL_DC: /* 7 */
1128 default:
1129 flags = LOOKUP_NAME_NONE;
1130 break;
1133 return flags;
1136 /***************************************************************************
1137 _lsa_LookupNames
1138 ***************************************************************************/
1140 NTSTATUS _lsa_LookupNames(struct pipes_struct *p,
1141 struct lsa_LookupNames *r)
1143 NTSTATUS status = NT_STATUS_NONE_MAPPED;
1144 struct lsa_info *handle;
1145 struct lsa_String *names = r->in.names;
1146 uint32 num_entries = r->in.num_names;
1147 struct lsa_RefDomainList *domains = NULL;
1148 struct lsa_TranslatedSid *rids = NULL;
1149 uint32 mapped_count = 0;
1150 int flags = 0;
1152 if (p->transport != NCACN_NP && p->transport != NCALRPC) {
1153 p->fault_state = DCERPC_FAULT_ACCESS_DENIED;
1154 return NT_STATUS_ACCESS_DENIED;
1157 if (num_entries > MAX_LOOKUP_SIDS) {
1158 num_entries = MAX_LOOKUP_SIDS;
1159 DEBUG(5,("_lsa_LookupNames: truncating name lookup list to %d\n",
1160 num_entries));
1163 flags = lsa_lookup_level_to_flags(r->in.level);
1165 domains = talloc_zero(p->mem_ctx, struct lsa_RefDomainList);
1166 if (!domains) {
1167 return NT_STATUS_NO_MEMORY;
1170 if (num_entries) {
1171 rids = talloc_zero_array(p->mem_ctx, struct lsa_TranslatedSid,
1172 num_entries);
1173 if (!rids) {
1174 return NT_STATUS_NO_MEMORY;
1176 } else {
1177 rids = NULL;
1180 if (!find_policy_by_hnd(p, r->in.handle, (void **)(void *)&handle)) {
1181 status = NT_STATUS_INVALID_HANDLE;
1182 goto done;
1185 if (handle->type != LSA_HANDLE_POLICY_TYPE) {
1186 return NT_STATUS_INVALID_HANDLE;
1189 /* check if the user has enough rights */
1190 if (!(handle->access & LSA_POLICY_LOOKUP_NAMES)) {
1191 status = NT_STATUS_ACCESS_DENIED;
1192 goto done;
1195 /* set up the LSA Lookup RIDs response */
1196 become_root(); /* lookup_name can require root privs */
1197 status = lookup_lsa_rids(p->mem_ctx, domains, rids, num_entries,
1198 names, flags, &mapped_count);
1199 unbecome_root();
1201 done:
1203 if (NT_STATUS_IS_OK(status) && (num_entries != 0) ) {
1204 if (mapped_count == 0) {
1205 status = NT_STATUS_NONE_MAPPED;
1206 } else if (mapped_count != num_entries) {
1207 status = STATUS_SOME_UNMAPPED;
1211 *r->out.count = mapped_count;
1212 *r->out.domains = domains;
1213 r->out.sids->sids = rids;
1214 r->out.sids->count = num_entries;
1216 return status;
1219 /***************************************************************************
1220 _lsa_LookupNames2
1221 ***************************************************************************/
1223 NTSTATUS _lsa_LookupNames2(struct pipes_struct *p,
1224 struct lsa_LookupNames2 *r)
1226 NTSTATUS status;
1227 struct lsa_LookupNames q;
1228 struct lsa_TransSidArray2 *sid_array2 = r->in.sids;
1229 struct lsa_TransSidArray *sid_array = NULL;
1230 uint32_t i;
1232 if (p->transport != NCACN_NP && p->transport != NCALRPC) {
1233 p->fault_state = DCERPC_FAULT_ACCESS_DENIED;
1234 return NT_STATUS_ACCESS_DENIED;
1237 sid_array = talloc_zero(p->mem_ctx, struct lsa_TransSidArray);
1238 if (!sid_array) {
1239 return NT_STATUS_NO_MEMORY;
1242 q.in.handle = r->in.handle;
1243 q.in.num_names = r->in.num_names;
1244 q.in.names = r->in.names;
1245 q.in.level = r->in.level;
1246 q.in.sids = sid_array;
1247 q.in.count = r->in.count;
1248 /* we do not know what this is for */
1249 /* = r->in.unknown1; */
1250 /* = r->in.unknown2; */
1252 q.out.domains = r->out.domains;
1253 q.out.sids = sid_array;
1254 q.out.count = r->out.count;
1256 status = _lsa_LookupNames(p, &q);
1258 sid_array2->count = sid_array->count;
1259 sid_array2->sids = talloc_array(p->mem_ctx, struct lsa_TranslatedSid2, sid_array->count);
1260 if (!sid_array2->sids) {
1261 return NT_STATUS_NO_MEMORY;
1264 for (i=0; i<sid_array->count; i++) {
1265 sid_array2->sids[i].sid_type = sid_array->sids[i].sid_type;
1266 sid_array2->sids[i].rid = sid_array->sids[i].rid;
1267 sid_array2->sids[i].sid_index = sid_array->sids[i].sid_index;
1268 sid_array2->sids[i].unknown = 0;
1271 r->out.sids = sid_array2;
1273 return status;
1276 static NTSTATUS _lsa_LookupNames_common(struct pipes_struct *p,
1277 struct lsa_LookupNames3 *r)
1279 NTSTATUS status;
1280 struct lsa_info *handle;
1281 struct lsa_String *names = r->in.names;
1282 uint32 num_entries = r->in.num_names;
1283 struct lsa_RefDomainList *domains = NULL;
1284 struct lsa_TranslatedSid3 *trans_sids = NULL;
1285 uint32 mapped_count = 0;
1286 int flags = 0;
1287 bool check_policy = true;
1289 switch (p->opnum) {
1290 case NDR_LSA_LOOKUPNAMES4:
1291 check_policy = false;
1292 break;
1293 case NDR_LSA_LOOKUPNAMES3:
1294 default:
1295 check_policy = true;
1298 if (num_entries > MAX_LOOKUP_SIDS) {
1299 num_entries = MAX_LOOKUP_SIDS;
1300 DEBUG(5,("_lsa_LookupNames3: truncating name lookup list to %d\n", num_entries));
1303 flags = lsa_lookup_level_to_flags(r->in.level);
1305 domains = talloc_zero(p->mem_ctx, struct lsa_RefDomainList);
1306 if (!domains) {
1307 return NT_STATUS_NO_MEMORY;
1310 if (num_entries) {
1311 trans_sids = talloc_zero_array(p->mem_ctx, struct lsa_TranslatedSid3,
1312 num_entries);
1313 if (!trans_sids) {
1314 return NT_STATUS_NO_MEMORY;
1316 } else {
1317 trans_sids = NULL;
1320 if (check_policy) {
1322 if (!find_policy_by_hnd(p, r->in.handle, (void **)(void *)&handle)) {
1323 status = NT_STATUS_INVALID_HANDLE;
1324 goto done;
1327 if (handle->type != LSA_HANDLE_POLICY_TYPE) {
1328 return NT_STATUS_INVALID_HANDLE;
1331 /* check if the user has enough rights */
1332 if (!(handle->access & LSA_POLICY_LOOKUP_NAMES)) {
1333 status = NT_STATUS_ACCESS_DENIED;
1334 goto done;
1338 /* set up the LSA Lookup SIDs response */
1339 become_root(); /* lookup_name can require root privs */
1340 status = lookup_lsa_sids(p->mem_ctx, domains, trans_sids, num_entries,
1341 names, flags, &mapped_count);
1342 unbecome_root();
1344 done:
1346 if (NT_STATUS_IS_OK(status)) {
1347 if (mapped_count == 0) {
1348 status = NT_STATUS_NONE_MAPPED;
1349 } else if (mapped_count != num_entries) {
1350 status = STATUS_SOME_UNMAPPED;
1354 *r->out.count = mapped_count;
1355 *r->out.domains = domains;
1356 r->out.sids->sids = trans_sids;
1357 r->out.sids->count = num_entries;
1359 return status;
1362 /***************************************************************************
1363 _lsa_LookupNames3
1364 ***************************************************************************/
1366 NTSTATUS _lsa_LookupNames3(struct pipes_struct *p,
1367 struct lsa_LookupNames3 *r)
1369 if (p->transport != NCACN_NP && p->transport != NCALRPC) {
1370 p->fault_state = DCERPC_FAULT_ACCESS_DENIED;
1371 return NT_STATUS_ACCESS_DENIED;
1374 return _lsa_LookupNames_common(p, r);
1377 /***************************************************************************
1378 _lsa_LookupNames4
1379 ***************************************************************************/
1381 NTSTATUS _lsa_LookupNames4(struct pipes_struct *p,
1382 struct lsa_LookupNames4 *r)
1384 struct lsa_LookupNames3 q;
1386 if (p->transport != NCACN_IP_TCP) {
1387 p->fault_state = DCERPC_FAULT_ACCESS_DENIED;
1388 return NT_STATUS_ACCESS_DENIED;
1391 /* No policy handle on this call. Restrict to crypto connections. */
1392 if (p->auth.auth_type != DCERPC_AUTH_TYPE_SCHANNEL ||
1393 p->auth.auth_level < DCERPC_AUTH_LEVEL_INTEGRITY) {
1394 DEBUG(1, ("_lsa_LookupNames4: The client %s is not using "
1395 "a secure connection over netlogon\n",
1396 get_remote_machine_name()));
1397 p->fault_state = DCERPC_FAULT_ACCESS_DENIED;
1398 return NT_STATUS_ACCESS_DENIED;
1401 q.in.handle = NULL;
1402 q.in.num_names = r->in.num_names;
1403 q.in.names = r->in.names;
1404 q.in.level = r->in.level;
1405 q.in.lookup_options = r->in.lookup_options;
1406 q.in.client_revision = r->in.client_revision;
1407 q.in.sids = r->in.sids;
1408 q.in.count = r->in.count;
1410 q.out.domains = r->out.domains;
1411 q.out.sids = r->out.sids;
1412 q.out.count = r->out.count;
1414 return _lsa_LookupNames_common(p, &q);
1417 /***************************************************************************
1418 _lsa_close. Also weird - needs to check if lsa handle is correct. JRA.
1419 ***************************************************************************/
1421 NTSTATUS _lsa_Close(struct pipes_struct *p, struct lsa_Close *r)
1423 if (p->transport != NCACN_NP && p->transport != NCALRPC) {
1424 p->fault_state = DCERPC_FAULT_ACCESS_DENIED;
1425 return NT_STATUS_ACCESS_DENIED;
1428 if (!find_policy_by_hnd(p, r->in.handle, NULL)) {
1429 return NT_STATUS_INVALID_HANDLE;
1432 close_policy_hnd(p, r->in.handle);
1433 ZERO_STRUCTP(r->out.handle);
1434 return NT_STATUS_OK;
1437 /***************************************************************************
1438 ***************************************************************************/
1440 static NTSTATUS lsa_lookup_trusted_domain_by_sid(TALLOC_CTX *mem_ctx,
1441 const struct dom_sid *sid,
1442 struct trustdom_info **info)
1444 NTSTATUS status;
1445 uint32_t num_domains = 0;
1446 struct trustdom_info **domains = NULL;
1447 int i;
1449 status = pdb_enum_trusteddoms(mem_ctx, &num_domains, &domains);
1450 if (!NT_STATUS_IS_OK(status)) {
1451 return status;
1454 for (i=0; i < num_domains; i++) {
1455 if (dom_sid_equal(&domains[i]->sid, sid)) {
1456 break;
1460 if (i == num_domains) {
1461 return NT_STATUS_INVALID_PARAMETER;
1464 *info = domains[i];
1466 return NT_STATUS_OK;
1469 /***************************************************************************
1470 ***************************************************************************/
1472 static NTSTATUS lsa_lookup_trusted_domain_by_name(TALLOC_CTX *mem_ctx,
1473 const char *netbios_domain_name,
1474 struct trustdom_info **info_p)
1476 NTSTATUS status;
1477 struct trustdom_info *info;
1478 struct pdb_trusted_domain *td;
1480 status = pdb_get_trusted_domain(mem_ctx, netbios_domain_name, &td);
1481 if (!NT_STATUS_IS_OK(status)) {
1482 return status;
1485 info = talloc(mem_ctx, struct trustdom_info);
1486 if (!info) {
1487 return NT_STATUS_NO_MEMORY;
1490 info->name = talloc_strdup(info, netbios_domain_name);
1491 NT_STATUS_HAVE_NO_MEMORY(info->name);
1493 sid_copy(&info->sid, &td->security_identifier);
1495 *info_p = info;
1497 return NT_STATUS_OK;
1500 /***************************************************************************
1501 _lsa_OpenSecret
1502 ***************************************************************************/
1504 NTSTATUS _lsa_OpenSecret(struct pipes_struct *p,
1505 struct lsa_OpenSecret *r)
1507 struct lsa_info *handle;
1508 struct security_descriptor *psd;
1509 NTSTATUS status;
1510 uint32_t acc_granted;
1512 if (!find_policy_by_hnd(p, r->in.handle, (void **)(void *)&handle)) {
1513 return NT_STATUS_INVALID_HANDLE;
1516 if (handle->type != LSA_HANDLE_POLICY_TYPE) {
1517 return NT_STATUS_INVALID_HANDLE;
1520 if (!r->in.name.string) {
1521 return NT_STATUS_INVALID_PARAMETER;
1524 /* Work out max allowed. */
1525 map_max_allowed_access(p->session_info->security_token,
1526 p->session_info->unix_token,
1527 &r->in.access_mask);
1529 /* map the generic bits to the lsa policy ones */
1530 se_map_generic(&r->in.access_mask, &lsa_secret_mapping);
1532 status = pdb_get_secret(p->mem_ctx, r->in.name.string,
1533 NULL,
1534 NULL,
1535 NULL,
1536 NULL,
1537 &psd);
1538 if (!NT_STATUS_IS_OK(status)) {
1539 return status;
1542 status = access_check_object(psd, p->session_info->security_token,
1543 SEC_PRIV_INVALID, SEC_PRIV_INVALID, 0,
1544 r->in.access_mask,
1545 &acc_granted, "_lsa_OpenSecret");
1546 if (!NT_STATUS_IS_OK(status)) {
1547 return status;
1550 status = create_lsa_policy_handle(p->mem_ctx, p,
1551 LSA_HANDLE_SECRET_TYPE,
1552 acc_granted,
1553 NULL,
1554 r->in.name.string,
1555 psd,
1556 r->out.sec_handle);
1557 if (!NT_STATUS_IS_OK(status)) {
1558 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1561 return NT_STATUS_OK;
1564 /***************************************************************************
1565 _lsa_OpenTrustedDomain_base
1566 ***************************************************************************/
1568 static NTSTATUS _lsa_OpenTrustedDomain_base(struct pipes_struct *p,
1569 uint32_t access_mask,
1570 struct trustdom_info *info,
1571 struct policy_handle *handle)
1573 struct security_descriptor *psd = NULL;
1574 size_t sd_size;
1575 uint32_t acc_granted;
1576 NTSTATUS status;
1578 /* des_access is for the account here, not the policy
1579 * handle - so don't check against policy handle. */
1581 /* Work out max allowed. */
1582 map_max_allowed_access(p->session_info->security_token,
1583 p->session_info->unix_token,
1584 &access_mask);
1586 /* map the generic bits to the lsa account ones */
1587 se_map_generic(&access_mask, &lsa_trusted_domain_mapping);
1589 /* get the generic lsa account SD until we store it */
1590 status = make_lsa_object_sd(p->mem_ctx, &psd, &sd_size,
1591 &lsa_trusted_domain_mapping,
1592 NULL, 0);
1593 if (!NT_STATUS_IS_OK(status)) {
1594 return status;
1597 status = access_check_object(psd, p->session_info->security_token,
1598 SEC_PRIV_INVALID, SEC_PRIV_INVALID, 0,
1599 access_mask, &acc_granted,
1600 "_lsa_OpenTrustedDomain");
1601 if (!NT_STATUS_IS_OK(status)) {
1602 return status;
1605 status = create_lsa_policy_handle(p->mem_ctx, p,
1606 LSA_HANDLE_TRUST_TYPE,
1607 acc_granted,
1608 &info->sid,
1609 info->name,
1610 psd,
1611 handle);
1612 if (!NT_STATUS_IS_OK(status)) {
1613 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1616 return NT_STATUS_OK;
1619 /***************************************************************************
1620 _lsa_OpenTrustedDomain
1621 ***************************************************************************/
1623 NTSTATUS _lsa_OpenTrustedDomain(struct pipes_struct *p,
1624 struct lsa_OpenTrustedDomain *r)
1626 struct lsa_info *handle = NULL;
1627 struct trustdom_info *info = NULL;
1628 NTSTATUS status;
1630 if (!find_policy_by_hnd(p, r->in.handle, (void **)(void *)&handle)) {
1631 return NT_STATUS_INVALID_HANDLE;
1634 if (handle->type != LSA_HANDLE_POLICY_TYPE) {
1635 return NT_STATUS_INVALID_HANDLE;
1638 status = lsa_lookup_trusted_domain_by_sid(p->mem_ctx,
1639 r->in.sid,
1640 &info);
1641 if (!NT_STATUS_IS_OK(status)) {
1642 return status;
1645 return _lsa_OpenTrustedDomain_base(p, r->in.access_mask, info,
1646 r->out.trustdom_handle);
1649 /***************************************************************************
1650 _lsa_OpenTrustedDomainByName
1651 ***************************************************************************/
1653 NTSTATUS _lsa_OpenTrustedDomainByName(struct pipes_struct *p,
1654 struct lsa_OpenTrustedDomainByName *r)
1656 struct lsa_info *handle = NULL;
1657 struct trustdom_info *info = NULL;
1658 NTSTATUS status;
1660 if (!find_policy_by_hnd(p, r->in.handle, (void **)(void *)&handle)) {
1661 return NT_STATUS_INVALID_HANDLE;
1664 if (handle->type != LSA_HANDLE_POLICY_TYPE) {
1665 return NT_STATUS_INVALID_HANDLE;
1668 status = lsa_lookup_trusted_domain_by_name(p->mem_ctx,
1669 r->in.name.string,
1670 &info);
1671 if (!NT_STATUS_IS_OK(status)) {
1672 return status;
1675 return _lsa_OpenTrustedDomain_base(p, r->in.access_mask, info,
1676 r->out.trustdom_handle);
1679 static NTSTATUS get_trustdom_auth_blob(struct pipes_struct *p,
1680 TALLOC_CTX *mem_ctx, DATA_BLOB *auth_blob,
1681 struct trustDomainPasswords *auth_struct)
1683 enum ndr_err_code ndr_err;
1684 DATA_BLOB lsession_key;
1685 NTSTATUS status;
1687 status = session_extract_session_key(p->session_info, &lsession_key, KEY_USE_16BYTES);
1688 if (!NT_STATUS_IS_OK(status)) {
1689 return NT_STATUS_INVALID_PARAMETER;
1692 arcfour_crypt_blob(auth_blob->data, auth_blob->length, &lsession_key);
1693 ndr_err = ndr_pull_struct_blob(auth_blob, mem_ctx,
1694 auth_struct,
1695 (ndr_pull_flags_fn_t)ndr_pull_trustDomainPasswords);
1696 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1697 return NT_STATUS_INVALID_PARAMETER;
1700 return NT_STATUS_OK;
1703 static NTSTATUS get_trustauth_inout_blob(TALLOC_CTX *mem_ctx,
1704 struct trustAuthInOutBlob *iopw,
1705 DATA_BLOB *trustauth_blob)
1707 enum ndr_err_code ndr_err;
1709 ndr_err = ndr_push_struct_blob(trustauth_blob, mem_ctx,
1710 iopw,
1711 (ndr_push_flags_fn_t)ndr_push_trustAuthInOutBlob);
1712 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1713 return NT_STATUS_INVALID_PARAMETER;
1716 return NT_STATUS_OK;
1719 /***************************************************************************
1720 _lsa_CreateTrustedDomainEx2
1721 ***************************************************************************/
1723 NTSTATUS _lsa_CreateTrustedDomainEx2(struct pipes_struct *p,
1724 struct lsa_CreateTrustedDomainEx2 *r)
1726 struct lsa_info *policy;
1727 NTSTATUS status;
1728 uint32_t acc_granted;
1729 struct security_descriptor *psd;
1730 size_t sd_size;
1731 struct pdb_trusted_domain td;
1732 struct trustDomainPasswords auth_struct;
1733 DATA_BLOB auth_blob;
1735 if (!IS_DC) {
1736 return NT_STATUS_NOT_SUPPORTED;
1739 if (!find_policy_by_hnd(p, r->in.policy_handle, (void **)(void *)&policy)) {
1740 return NT_STATUS_INVALID_HANDLE;
1743 if (!(policy->access & LSA_POLICY_TRUST_ADMIN)) {
1744 return NT_STATUS_ACCESS_DENIED;
1747 if (p->session_info->unix_token->uid != sec_initial_uid() &&
1748 !nt_token_check_domain_rid(p->session_info->security_token, DOMAIN_RID_ADMINS)) {
1749 return NT_STATUS_ACCESS_DENIED;
1752 /* Work out max allowed. */
1753 map_max_allowed_access(p->session_info->security_token,
1754 p->session_info->unix_token,
1755 &r->in.access_mask);
1757 /* map the generic bits to the lsa policy ones */
1758 se_map_generic(&r->in.access_mask, &lsa_account_mapping);
1760 status = make_lsa_object_sd(p->mem_ctx, &psd, &sd_size,
1761 &lsa_trusted_domain_mapping,
1762 NULL, 0);
1763 if (!NT_STATUS_IS_OK(status)) {
1764 return status;
1767 status = access_check_object(psd, p->session_info->security_token,
1768 SEC_PRIV_INVALID, SEC_PRIV_INVALID, 0,
1769 r->in.access_mask, &acc_granted,
1770 "_lsa_CreateTrustedDomainEx2");
1771 if (!NT_STATUS_IS_OK(status)) {
1772 return status;
1775 ZERO_STRUCT(td);
1777 td.domain_name = talloc_strdup(p->mem_ctx,
1778 r->in.info->domain_name.string);
1779 if (td.domain_name == NULL) {
1780 return NT_STATUS_NO_MEMORY;
1782 td.netbios_name = talloc_strdup(p->mem_ctx,
1783 r->in.info->netbios_name.string);
1784 if (td.netbios_name == NULL) {
1785 return NT_STATUS_NO_MEMORY;
1787 sid_copy(&td.security_identifier, r->in.info->sid);
1788 td.trust_direction = r->in.info->trust_direction;
1789 td.trust_type = r->in.info->trust_type;
1790 td.trust_attributes = r->in.info->trust_attributes;
1792 if (r->in.auth_info_internal->auth_blob.size != 0) {
1793 auth_blob.length = r->in.auth_info_internal->auth_blob.size;
1794 auth_blob.data = r->in.auth_info_internal->auth_blob.data;
1796 status = get_trustdom_auth_blob(p, p->mem_ctx, &auth_blob, &auth_struct);
1797 if (!NT_STATUS_IS_OK(status)) {
1798 return NT_STATUS_UNSUCCESSFUL;
1801 status = get_trustauth_inout_blob(p->mem_ctx, &auth_struct.incoming, &td.trust_auth_incoming);
1802 if (!NT_STATUS_IS_OK(status)) {
1803 return NT_STATUS_UNSUCCESSFUL;
1806 status = get_trustauth_inout_blob(p->mem_ctx, &auth_struct.outgoing, &td.trust_auth_outgoing);
1807 if (!NT_STATUS_IS_OK(status)) {
1808 return NT_STATUS_UNSUCCESSFUL;
1810 } else {
1811 td.trust_auth_incoming.data = NULL;
1812 td.trust_auth_incoming.length = 0;
1813 td.trust_auth_outgoing.data = NULL;
1814 td.trust_auth_outgoing.length = 0;
1817 status = pdb_set_trusted_domain(r->in.info->domain_name.string, &td);
1818 if (!NT_STATUS_IS_OK(status)) {
1819 return status;
1822 status = create_lsa_policy_handle(p->mem_ctx, p,
1823 LSA_HANDLE_TRUST_TYPE,
1824 acc_granted,
1825 r->in.info->sid,
1826 r->in.info->netbios_name.string,
1827 psd,
1828 r->out.trustdom_handle);
1829 if (!NT_STATUS_IS_OK(status)) {
1830 pdb_del_trusted_domain(r->in.info->netbios_name.string);
1831 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1834 return NT_STATUS_OK;
1837 /***************************************************************************
1838 _lsa_CreateTrustedDomainEx
1839 ***************************************************************************/
1841 NTSTATUS _lsa_CreateTrustedDomainEx(struct pipes_struct *p,
1842 struct lsa_CreateTrustedDomainEx *r)
1844 struct lsa_CreateTrustedDomainEx2 q;
1845 struct lsa_TrustDomainInfoAuthInfoInternal auth_info;
1847 ZERO_STRUCT(auth_info);
1849 q.in.policy_handle = r->in.policy_handle;
1850 q.in.info = r->in.info;
1851 q.in.auth_info_internal = &auth_info;
1852 q.in.access_mask = r->in.access_mask;
1853 q.out.trustdom_handle = r->out.trustdom_handle;
1855 return _lsa_CreateTrustedDomainEx2(p, &q);
1858 /***************************************************************************
1859 _lsa_CreateTrustedDomain
1860 ***************************************************************************/
1862 NTSTATUS _lsa_CreateTrustedDomain(struct pipes_struct *p,
1863 struct lsa_CreateTrustedDomain *r)
1865 struct lsa_CreateTrustedDomainEx2 c;
1866 struct lsa_TrustDomainInfoInfoEx info;
1867 struct lsa_TrustDomainInfoAuthInfoInternal auth_info;
1869 ZERO_STRUCT(auth_info);
1871 info.domain_name = r->in.info->name;
1872 info.netbios_name = r->in.info->name;
1873 info.sid = r->in.info->sid;
1874 info.trust_direction = LSA_TRUST_DIRECTION_OUTBOUND;
1875 info.trust_type = LSA_TRUST_TYPE_DOWNLEVEL;
1876 info.trust_attributes = 0;
1878 c.in.policy_handle = r->in.policy_handle;
1879 c.in.info = &info;
1880 c.in.auth_info_internal = &auth_info;
1881 c.in.access_mask = r->in.access_mask;
1882 c.out.trustdom_handle = r->out.trustdom_handle;
1884 return _lsa_CreateTrustedDomainEx2(p, &c);
1887 /***************************************************************************
1888 _lsa_DeleteTrustedDomain
1889 ***************************************************************************/
1891 NTSTATUS _lsa_DeleteTrustedDomain(struct pipes_struct *p,
1892 struct lsa_DeleteTrustedDomain *r)
1894 NTSTATUS status;
1895 struct lsa_info *handle;
1896 struct pdb_trusted_domain *td;
1898 /* find the connection policy handle. */
1899 if (!find_policy_by_hnd(p, r->in.handle, (void **)(void *)&handle)) {
1900 return NT_STATUS_INVALID_HANDLE;
1903 if (handle->type != LSA_HANDLE_POLICY_TYPE) {
1904 return NT_STATUS_INVALID_HANDLE;
1907 if (!(handle->access & LSA_POLICY_TRUST_ADMIN)) {
1908 return NT_STATUS_ACCESS_DENIED;
1911 status = pdb_get_trusted_domain_by_sid(p->mem_ctx, r->in.dom_sid, &td);
1912 if (!NT_STATUS_IS_OK(status)) {
1913 return status;
1916 if (td->netbios_name == NULL || *td->netbios_name == '\0') {
1917 DEBUG(10, ("Missing netbios name for for trusted domain %s.\n",
1918 sid_string_tos(r->in.dom_sid)));
1919 return NT_STATUS_UNSUCCESSFUL;
1922 status = pdb_del_trusted_domain(td->netbios_name);
1923 if (!NT_STATUS_IS_OK(status)) {
1924 return status;
1927 return NT_STATUS_OK;
1930 /***************************************************************************
1931 _lsa_CloseTrustedDomainEx
1932 ***************************************************************************/
1934 NTSTATUS _lsa_CloseTrustedDomainEx(struct pipes_struct *p,
1935 struct lsa_CloseTrustedDomainEx *r)
1937 return NT_STATUS_NOT_IMPLEMENTED;
1940 /***************************************************************************
1941 _lsa_QueryTrustedDomainInfo
1942 ***************************************************************************/
1944 static NTSTATUS pdb_trusted_domain_2_info_ex(TALLOC_CTX *mem_ctx,
1945 struct pdb_trusted_domain *td,
1946 struct lsa_TrustDomainInfoInfoEx *info_ex)
1948 if (td->domain_name == NULL ||
1949 td->netbios_name == NULL ||
1950 is_null_sid(&td->security_identifier)) {
1951 return NT_STATUS_INVALID_PARAMETER;
1954 info_ex->domain_name.string = talloc_strdup(mem_ctx, td->domain_name);
1955 info_ex->netbios_name.string = talloc_strdup(mem_ctx, td->netbios_name);
1956 info_ex->sid = dom_sid_dup(mem_ctx, &td->security_identifier);
1957 if (info_ex->domain_name.string == NULL ||
1958 info_ex->netbios_name.string == NULL ||
1959 info_ex->sid == NULL) {
1960 return NT_STATUS_NO_MEMORY;
1963 info_ex->trust_direction = td->trust_direction;
1964 info_ex->trust_type = td->trust_type;
1965 info_ex->trust_attributes = td->trust_attributes;
1967 return NT_STATUS_OK;
1970 NTSTATUS _lsa_QueryTrustedDomainInfo(struct pipes_struct *p,
1971 struct lsa_QueryTrustedDomainInfo *r)
1973 NTSTATUS status;
1974 struct lsa_info *handle;
1975 union lsa_TrustedDomainInfo *info;
1976 struct pdb_trusted_domain *td;
1977 uint32_t acc_required;
1979 /* find the connection policy handle. */
1980 if (!find_policy_by_hnd(p, r->in.trustdom_handle, (void **)(void *)&handle)) {
1981 return NT_STATUS_INVALID_HANDLE;
1984 if (handle->type != LSA_HANDLE_TRUST_TYPE) {
1985 return NT_STATUS_INVALID_HANDLE;
1988 switch (r->in.level) {
1989 case LSA_TRUSTED_DOMAIN_INFO_NAME:
1990 acc_required = LSA_TRUSTED_QUERY_DOMAIN_NAME;
1991 break;
1992 case LSA_TRUSTED_DOMAIN_INFO_CONTROLLERS:
1993 acc_required = LSA_TRUSTED_QUERY_CONTROLLERS;
1994 break;
1995 case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
1996 acc_required = LSA_TRUSTED_QUERY_POSIX;
1997 break;
1998 case LSA_TRUSTED_DOMAIN_INFO_PASSWORD:
1999 acc_required = LSA_TRUSTED_QUERY_AUTH;
2000 break;
2001 case LSA_TRUSTED_DOMAIN_INFO_BASIC:
2002 acc_required = LSA_TRUSTED_QUERY_DOMAIN_NAME;
2003 break;
2004 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
2005 acc_required = LSA_TRUSTED_QUERY_DOMAIN_NAME;
2006 break;
2007 case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO:
2008 acc_required = LSA_TRUSTED_QUERY_AUTH;
2009 break;
2010 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
2011 acc_required = LSA_TRUSTED_QUERY_DOMAIN_NAME |
2012 LSA_TRUSTED_QUERY_POSIX |
2013 LSA_TRUSTED_QUERY_AUTH;
2014 break;
2015 case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO_INTERNAL:
2016 acc_required = LSA_TRUSTED_QUERY_AUTH;
2017 break;
2018 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_INTERNAL:
2019 acc_required = LSA_TRUSTED_QUERY_DOMAIN_NAME |
2020 LSA_TRUSTED_QUERY_POSIX |
2021 LSA_TRUSTED_QUERY_AUTH;
2022 break;
2023 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX2_INTERNAL:
2024 acc_required = LSA_TRUSTED_QUERY_DOMAIN_NAME;
2025 break;
2026 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_2_INTERNAL:
2027 acc_required = LSA_TRUSTED_QUERY_DOMAIN_NAME |
2028 LSA_TRUSTED_QUERY_POSIX |
2029 LSA_TRUSTED_QUERY_AUTH;
2030 break;
2031 case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
2032 acc_required = LSA_TRUSTED_QUERY_POSIX;
2033 break;
2034 default:
2035 return NT_STATUS_INVALID_PARAMETER;
2038 if (!(handle->access & acc_required)) {
2039 return NT_STATUS_ACCESS_DENIED;
2042 status = pdb_get_trusted_domain_by_sid(p->mem_ctx, &handle->sid, &td);
2043 if (!NT_STATUS_IS_OK(status)) {
2044 return status;
2047 info = talloc_zero(p->mem_ctx, union lsa_TrustedDomainInfo);
2048 if (!info) {
2049 return NT_STATUS_NO_MEMORY;
2052 switch (r->in.level) {
2053 case LSA_TRUSTED_DOMAIN_INFO_NAME:
2054 init_lsa_StringLarge(&info->name.netbios_name, td->netbios_name);
2055 break;
2056 case LSA_TRUSTED_DOMAIN_INFO_CONTROLLERS:
2057 return NT_STATUS_INVALID_PARAMETER;
2058 case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
2059 info->posix_offset.posix_offset = *td->trust_posix_offset;
2060 break;
2061 case LSA_TRUSTED_DOMAIN_INFO_PASSWORD:
2062 return NT_STATUS_INVALID_INFO_CLASS;
2063 case LSA_TRUSTED_DOMAIN_INFO_BASIC:
2064 return NT_STATUS_INVALID_PARAMETER;
2065 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
2066 status = pdb_trusted_domain_2_info_ex(info, td, &info->info_ex);
2067 if (!NT_STATUS_IS_OK(status)) {
2068 return status;
2070 break;
2071 case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO:
2072 return NT_STATUS_INVALID_INFO_CLASS;
2073 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
2074 status = pdb_trusted_domain_2_info_ex(info, td,
2075 &info->full_info.info_ex);
2076 if (!NT_STATUS_IS_OK(status)) {
2077 return status;
2079 info->full_info.posix_offset.posix_offset = *td->trust_posix_offset;
2080 status = auth_blob_2_auth_info(p->mem_ctx,
2081 td->trust_auth_incoming,
2082 td->trust_auth_outgoing,
2083 &info->full_info.auth_info);
2084 if (!NT_STATUS_IS_OK(status)) {
2085 return status;
2087 break;
2088 case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO_INTERNAL:
2089 return NT_STATUS_INVALID_INFO_CLASS;
2090 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_INTERNAL:
2091 return NT_STATUS_INVALID_INFO_CLASS;
2092 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX2_INTERNAL:
2093 return NT_STATUS_INVALID_PARAMETER;
2094 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_2_INTERNAL:
2095 info->full_info2_internal.posix_offset.posix_offset = *td->trust_posix_offset;
2096 status = auth_blob_2_auth_info(p->mem_ctx,
2097 td->trust_auth_incoming,
2098 td->trust_auth_outgoing,
2099 &info->full_info2_internal.auth_info);
2100 if (!NT_STATUS_IS_OK(status)) {
2101 return status;
2103 break;
2104 case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
2105 info->enc_types.enc_types = *td->supported_enc_type;
2106 break;
2107 default:
2108 return NT_STATUS_INVALID_PARAMETER;
2111 *r->out.info = info;
2113 return NT_STATUS_OK;
2116 /***************************************************************************
2117 _lsa_QueryTrustedDomainInfoBySid
2118 ***************************************************************************/
2120 NTSTATUS _lsa_QueryTrustedDomainInfoBySid(struct pipes_struct *p,
2121 struct lsa_QueryTrustedDomainInfoBySid *r)
2123 NTSTATUS status;
2124 struct policy_handle trustdom_handle;
2125 struct lsa_OpenTrustedDomain o;
2126 struct lsa_QueryTrustedDomainInfo q;
2127 struct lsa_Close c;
2129 o.in.handle = r->in.handle;
2130 o.in.sid = r->in.dom_sid;
2131 o.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2132 o.out.trustdom_handle = &trustdom_handle;
2134 status = _lsa_OpenTrustedDomain(p, &o);
2135 if (!NT_STATUS_IS_OK(status)) {
2136 return status;
2139 q.in.trustdom_handle = &trustdom_handle;
2140 q.in.level = r->in.level;
2141 q.out.info = r->out.info;
2143 status = _lsa_QueryTrustedDomainInfo(p, &q);
2144 if (!NT_STATUS_IS_OK(status)) {
2145 return status;
2148 c.in.handle = &trustdom_handle;
2149 c.out.handle = &trustdom_handle;
2151 return _lsa_Close(p, &c);
2154 /***************************************************************************
2155 _lsa_QueryTrustedDomainInfoByName
2156 ***************************************************************************/
2158 NTSTATUS _lsa_QueryTrustedDomainInfoByName(struct pipes_struct *p,
2159 struct lsa_QueryTrustedDomainInfoByName *r)
2161 NTSTATUS status;
2162 struct policy_handle trustdom_handle;
2163 struct lsa_OpenTrustedDomainByName o;
2164 struct lsa_QueryTrustedDomainInfo q;
2165 struct lsa_Close c;
2167 o.in.handle = r->in.handle;
2168 o.in.name.string = r->in.trusted_domain->string;
2169 o.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2170 o.out.trustdom_handle = &trustdom_handle;
2172 status = _lsa_OpenTrustedDomainByName(p, &o);
2173 if (!NT_STATUS_IS_OK(status)) {
2174 if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_DOMAIN)) {
2175 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2177 return status;
2180 q.in.trustdom_handle = &trustdom_handle;
2181 q.in.level = r->in.level;
2182 q.out.info = r->out.info;
2184 status = _lsa_QueryTrustedDomainInfo(p, &q);
2185 if (!NT_STATUS_IS_OK(status)) {
2186 return status;
2189 c.in.handle = &trustdom_handle;
2190 c.out.handle = &trustdom_handle;
2192 return _lsa_Close(p, &c);
2195 /***************************************************************************
2196 _lsa_CreateSecret
2197 ***************************************************************************/
2199 NTSTATUS _lsa_CreateSecret(struct pipes_struct *p,
2200 struct lsa_CreateSecret *r)
2202 NTSTATUS status;
2203 struct lsa_info *handle;
2204 uint32_t acc_granted;
2205 struct security_descriptor *psd;
2206 size_t sd_size;
2208 /* find the connection policy handle. */
2209 if (!find_policy_by_hnd(p, r->in.handle, (void **)(void *)&handle)) {
2210 return NT_STATUS_INVALID_HANDLE;
2213 if (handle->type != LSA_HANDLE_POLICY_TYPE) {
2214 return NT_STATUS_INVALID_HANDLE;
2217 /* check if the user has enough rights */
2219 if (!(handle->access & LSA_POLICY_CREATE_SECRET)) {
2220 return NT_STATUS_ACCESS_DENIED;
2223 /* Work out max allowed. */
2224 map_max_allowed_access(p->session_info->security_token,
2225 p->session_info->unix_token,
2226 &r->in.access_mask);
2228 /* map the generic bits to the lsa policy ones */
2229 se_map_generic(&r->in.access_mask, &lsa_secret_mapping);
2231 status = make_lsa_object_sd(p->mem_ctx, &psd, &sd_size,
2232 &lsa_secret_mapping,
2233 NULL, 0);
2234 if (!NT_STATUS_IS_OK(status)) {
2235 return status;
2238 status = access_check_object(psd, p->session_info->security_token,
2239 SEC_PRIV_INVALID, SEC_PRIV_INVALID, 0,
2240 r->in.access_mask,
2241 &acc_granted, "_lsa_CreateSecret");
2242 if (!NT_STATUS_IS_OK(status)) {
2243 return status;
2246 if (!r->in.name.string) {
2247 return NT_STATUS_INVALID_PARAMETER;
2250 if (strlen(r->in.name.string) > 128) {
2251 return NT_STATUS_NAME_TOO_LONG;
2254 status = pdb_get_secret(p->mem_ctx, r->in.name.string,
2255 NULL, NULL, NULL, NULL, NULL);
2256 if (NT_STATUS_IS_OK(status)) {
2257 return NT_STATUS_OBJECT_NAME_COLLISION;
2260 status = pdb_set_secret(r->in.name.string, NULL, NULL, psd);
2261 if (!NT_STATUS_IS_OK(status)) {
2262 return status;
2265 status = create_lsa_policy_handle(p->mem_ctx, p,
2266 LSA_HANDLE_SECRET_TYPE,
2267 acc_granted,
2268 NULL,
2269 r->in.name.string,
2270 psd,
2271 r->out.sec_handle);
2272 if (!NT_STATUS_IS_OK(status)) {
2273 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2276 return NT_STATUS_OK;
2279 /***************************************************************************
2280 _lsa_SetSecret
2281 ***************************************************************************/
2283 NTSTATUS _lsa_SetSecret(struct pipes_struct *p,
2284 struct lsa_SetSecret *r)
2286 NTSTATUS status;
2287 struct lsa_info *info = NULL;
2288 DATA_BLOB blob_new, blob_old;
2289 DATA_BLOB cleartext_blob_new = data_blob_null;
2290 DATA_BLOB cleartext_blob_old = data_blob_null;
2291 DATA_BLOB *cleartext_blob_new_p = NULL;
2292 DATA_BLOB *cleartext_blob_old_p = NULL;
2293 DATA_BLOB session_key;
2295 if (!find_policy_by_hnd(p, r->in.sec_handle, (void **)(void *)&info)) {
2296 return NT_STATUS_INVALID_HANDLE;
2299 if (info->type != LSA_HANDLE_SECRET_TYPE) {
2300 return NT_STATUS_INVALID_HANDLE;
2303 if (!(info->access & LSA_SECRET_SET_VALUE)) {
2304 return NT_STATUS_ACCESS_DENIED;
2307 status = session_extract_session_key(p->session_info, &session_key, KEY_USE_16BYTES);
2308 if(!NT_STATUS_IS_OK(status)) {
2309 return status;
2312 if (r->in.new_val) {
2313 blob_new = data_blob_const(r->in.new_val->data,
2314 r->in.new_val->length);
2316 status = sess_decrypt_blob(p->mem_ctx, &blob_new,
2317 &session_key,
2318 &cleartext_blob_new);
2319 if (!NT_STATUS_IS_OK(status)) {
2320 return status;
2323 cleartext_blob_new_p = &cleartext_blob_new;
2326 if (r->in.old_val) {
2327 blob_old = data_blob_const(r->in.old_val->data,
2328 r->in.old_val->length);
2330 status = sess_decrypt_blob(p->mem_ctx, &blob_old,
2331 &session_key,
2332 &cleartext_blob_old);
2333 if (!NT_STATUS_IS_OK(status)) {
2334 return status;
2337 cleartext_blob_old_p = &cleartext_blob_old;
2340 status = pdb_set_secret(info->name, cleartext_blob_new_p, cleartext_blob_old_p, NULL);
2341 if (!NT_STATUS_IS_OK(status)) {
2342 return status;
2345 #ifdef DEBUG_PASSWORD
2346 DEBUG(10,("_lsa_SetSecret: successfully set new secret\n"));
2347 dump_data(10, cleartext_blob_new.data, cleartext_blob_new.length);
2348 DEBUG(10,("_lsa_SetSecret: successfully set old secret\n"));
2349 dump_data(10, cleartext_blob_old.data, cleartext_blob_old.length);
2350 #endif
2352 return NT_STATUS_OK;
2355 /***************************************************************************
2356 _lsa_QuerySecret
2357 ***************************************************************************/
2359 NTSTATUS _lsa_QuerySecret(struct pipes_struct *p,
2360 struct lsa_QuerySecret *r)
2362 struct lsa_info *info = NULL;
2363 DATA_BLOB blob_new, blob_old;
2364 DATA_BLOB blob_new_crypt, blob_old_crypt;
2365 DATA_BLOB session_key;
2366 NTTIME nttime_new, nttime_old;
2367 NTSTATUS status;
2369 if (!find_policy_by_hnd(p, r->in.sec_handle, (void **)(void *)&info)) {
2370 return NT_STATUS_INVALID_HANDLE;
2373 if (info->type != LSA_HANDLE_SECRET_TYPE) {
2374 return NT_STATUS_INVALID_HANDLE;
2377 if (!(info->access & LSA_SECRET_QUERY_VALUE)) {
2378 return NT_STATUS_ACCESS_DENIED;
2381 status = pdb_get_secret(p->mem_ctx, info->name,
2382 &blob_new, &nttime_new,
2383 &blob_old, &nttime_old,
2384 NULL);
2385 if (!NT_STATUS_IS_OK(status)) {
2386 return status;
2389 status = session_extract_session_key(p->session_info, &session_key, KEY_USE_16BYTES);
2390 if(!NT_STATUS_IS_OK(status)) {
2391 return status;
2394 if (r->in.new_val) {
2395 if (blob_new.length) {
2396 if (!r->out.new_val->buf) {
2397 r->out.new_val->buf = talloc_zero(p->mem_ctx, struct lsa_DATA_BUF);
2399 if (!r->out.new_val->buf) {
2400 return NT_STATUS_NO_MEMORY;
2403 blob_new_crypt = sess_encrypt_blob(p->mem_ctx, &blob_new,
2404 &session_key);
2405 if (!blob_new_crypt.length) {
2406 return NT_STATUS_NO_MEMORY;
2409 r->out.new_val->buf->data = blob_new_crypt.data;
2410 r->out.new_val->buf->length = blob_new_crypt.length;
2411 r->out.new_val->buf->size = blob_new_crypt.length;
2415 if (r->in.old_val) {
2416 if (blob_old.length) {
2417 if (!r->out.old_val->buf) {
2418 r->out.old_val->buf = talloc_zero(p->mem_ctx, struct lsa_DATA_BUF);
2420 if (!r->out.old_val->buf) {
2421 return NT_STATUS_NO_MEMORY;
2424 blob_old_crypt = sess_encrypt_blob(p->mem_ctx, &blob_old,
2425 &session_key);
2426 if (!blob_old_crypt.length) {
2427 return NT_STATUS_NO_MEMORY;
2430 r->out.old_val->buf->data = blob_old_crypt.data;
2431 r->out.old_val->buf->length = blob_old_crypt.length;
2432 r->out.old_val->buf->size = blob_old_crypt.length;
2436 if (r->out.new_mtime) {
2437 *r->out.new_mtime = nttime_new;
2440 if (r->out.old_mtime) {
2441 *r->out.old_mtime = nttime_old;
2444 return NT_STATUS_OK;
2447 /***************************************************************************
2448 _lsa_DeleteObject
2449 ***************************************************************************/
2451 NTSTATUS _lsa_DeleteObject(struct pipes_struct *p,
2452 struct lsa_DeleteObject *r)
2454 NTSTATUS status;
2455 struct lsa_info *info = NULL;
2457 if (!find_policy_by_hnd(p, r->in.handle, (void **)(void *)&info)) {
2458 return NT_STATUS_INVALID_HANDLE;
2461 if (!(info->access & SEC_STD_DELETE)) {
2462 return NT_STATUS_ACCESS_DENIED;
2465 switch (info->type) {
2466 case LSA_HANDLE_ACCOUNT_TYPE:
2467 status = privilege_delete_account(&info->sid);
2468 if (!NT_STATUS_IS_OK(status)) {
2469 DEBUG(10,("_lsa_DeleteObject: privilege_delete_account gave: %s\n",
2470 nt_errstr(status)));
2471 return status;
2473 break;
2474 case LSA_HANDLE_TRUST_TYPE:
2475 if (!pdb_del_trusteddom_pw(info->name)) {
2476 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2478 status = NT_STATUS_OK;
2479 break;
2480 case LSA_HANDLE_SECRET_TYPE:
2481 status = pdb_delete_secret(info->name);
2482 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2483 return NT_STATUS_INVALID_HANDLE;
2485 break;
2486 default:
2487 return NT_STATUS_INVALID_HANDLE;
2490 close_policy_hnd(p, r->in.handle);
2491 ZERO_STRUCTP(r->out.handle);
2493 return status;
2496 /***************************************************************************
2497 _lsa_EnumPrivs
2498 ***************************************************************************/
2500 NTSTATUS _lsa_EnumPrivs(struct pipes_struct *p,
2501 struct lsa_EnumPrivs *r)
2503 struct lsa_info *handle;
2504 uint32 i;
2505 uint32 enum_context = *r->in.resume_handle;
2506 int num_privs = num_privileges_in_short_list();
2507 struct lsa_PrivEntry *entries = NULL;
2509 /* remember that the enum_context starts at 0 and not 1 */
2511 if ( enum_context >= num_privs )
2512 return NT_STATUS_NO_MORE_ENTRIES;
2514 DEBUG(10,("_lsa_EnumPrivs: enum_context:%d total entries:%d\n",
2515 enum_context, num_privs));
2517 if (!find_policy_by_hnd(p, r->in.handle, (void **)(void *)&handle))
2518 return NT_STATUS_INVALID_HANDLE;
2520 if (handle->type != LSA_HANDLE_POLICY_TYPE) {
2521 return NT_STATUS_INVALID_HANDLE;
2524 /* check if the user has enough rights
2525 I don't know if it's the right one. not documented. */
2527 if (!(handle->access & LSA_POLICY_VIEW_LOCAL_INFORMATION))
2528 return NT_STATUS_ACCESS_DENIED;
2530 if (num_privs) {
2531 entries = talloc_zero_array(p->mem_ctx, struct lsa_PrivEntry, num_privs);
2532 if (!entries) {
2533 return NT_STATUS_NO_MEMORY;
2535 } else {
2536 entries = NULL;
2539 for (i = 0; i < num_privs; i++) {
2540 if( i < enum_context) {
2542 init_lsa_StringLarge(&entries[i].name, NULL);
2544 entries[i].luid.low = 0;
2545 entries[i].luid.high = 0;
2546 } else {
2548 init_lsa_StringLarge(&entries[i].name, sec_privilege_name_from_index(i));
2550 entries[i].luid.low = sec_privilege_from_index(i);
2551 entries[i].luid.high = 0;
2555 enum_context = num_privs;
2557 *r->out.resume_handle = enum_context;
2558 r->out.privs->count = num_privs;
2559 r->out.privs->privs = entries;
2561 return NT_STATUS_OK;
2564 /***************************************************************************
2565 _lsa_LookupPrivDisplayName
2566 ***************************************************************************/
2568 NTSTATUS _lsa_LookupPrivDisplayName(struct pipes_struct *p,
2569 struct lsa_LookupPrivDisplayName *r)
2571 struct lsa_info *handle;
2572 const char *description;
2573 struct lsa_StringLarge *lsa_name;
2575 if (!find_policy_by_hnd(p, r->in.handle, (void **)(void *)&handle))
2576 return NT_STATUS_INVALID_HANDLE;
2578 if (handle->type != LSA_HANDLE_POLICY_TYPE) {
2579 return NT_STATUS_INVALID_HANDLE;
2582 /* check if the user has enough rights */
2585 * I don't know if it's the right one. not documented.
2587 if (!(handle->access & LSA_POLICY_VIEW_LOCAL_INFORMATION))
2588 return NT_STATUS_ACCESS_DENIED;
2590 DEBUG(10,("_lsa_LookupPrivDisplayName: name = %s\n", r->in.name->string));
2592 description = get_privilege_dispname(r->in.name->string);
2593 if (!description) {
2594 DEBUG(10,("_lsa_LookupPrivDisplayName: doesn't exist\n"));
2595 return NT_STATUS_NO_SUCH_PRIVILEGE;
2598 DEBUG(10,("_lsa_LookupPrivDisplayName: display name = %s\n", description));
2600 lsa_name = talloc_zero(p->mem_ctx, struct lsa_StringLarge);
2601 if (!lsa_name) {
2602 return NT_STATUS_NO_MEMORY;
2605 init_lsa_StringLarge(lsa_name, description);
2607 *r->out.returned_language_id = r->in.language_id;
2608 *r->out.disp_name = lsa_name;
2610 return NT_STATUS_OK;
2613 /***************************************************************************
2614 _lsa_EnumAccounts
2615 ***************************************************************************/
2617 NTSTATUS _lsa_EnumAccounts(struct pipes_struct *p,
2618 struct lsa_EnumAccounts *r)
2620 struct lsa_info *handle;
2621 struct dom_sid *sid_list;
2622 int i, j, num_entries;
2623 NTSTATUS status;
2624 struct lsa_SidPtr *sids = NULL;
2626 if (!find_policy_by_hnd(p, r->in.handle, (void **)(void *)&handle))
2627 return NT_STATUS_INVALID_HANDLE;
2629 if (handle->type != LSA_HANDLE_POLICY_TYPE) {
2630 return NT_STATUS_INVALID_HANDLE;
2633 if (!(handle->access & LSA_POLICY_VIEW_LOCAL_INFORMATION))
2634 return NT_STATUS_ACCESS_DENIED;
2636 sid_list = NULL;
2637 num_entries = 0;
2639 /* The only way we can currently find out all the SIDs that have been
2640 privileged is to scan all privileges */
2642 status = privilege_enumerate_accounts(&sid_list, &num_entries);
2643 if (!NT_STATUS_IS_OK(status)) {
2644 return status;
2647 if (*r->in.resume_handle >= num_entries) {
2648 return NT_STATUS_NO_MORE_ENTRIES;
2651 if (num_entries - *r->in.resume_handle) {
2652 sids = talloc_zero_array(p->mem_ctx, struct lsa_SidPtr,
2653 num_entries - *r->in.resume_handle);
2654 if (!sids) {
2655 talloc_free(sid_list);
2656 return NT_STATUS_NO_MEMORY;
2659 for (i = *r->in.resume_handle, j = 0; i < num_entries; i++, j++) {
2660 sids[j].sid = dom_sid_dup(p->mem_ctx, &sid_list[i]);
2661 if (!sids[j].sid) {
2662 talloc_free(sid_list);
2663 return NT_STATUS_NO_MEMORY;
2668 talloc_free(sid_list);
2670 *r->out.resume_handle = num_entries;
2671 r->out.sids->num_sids = num_entries;
2672 r->out.sids->sids = sids;
2674 return NT_STATUS_OK;
2677 /***************************************************************************
2678 _lsa_GetUserName
2679 ***************************************************************************/
2681 NTSTATUS _lsa_GetUserName(struct pipes_struct *p,
2682 struct lsa_GetUserName *r)
2684 const char *username, *domname;
2685 struct lsa_String *account_name = NULL;
2686 struct lsa_String *authority_name = NULL;
2688 if (p->transport != NCACN_NP && p->transport != NCALRPC) {
2689 p->fault_state = DCERPC_FAULT_ACCESS_DENIED;
2690 return NT_STATUS_ACCESS_DENIED;
2693 if (r->in.account_name &&
2694 *r->in.account_name) {
2695 return NT_STATUS_INVALID_PARAMETER;
2698 if (r->in.authority_name &&
2699 *r->in.authority_name) {
2700 return NT_STATUS_INVALID_PARAMETER;
2703 if (security_session_user_level(p->session_info, NULL) < SECURITY_USER) {
2705 * I'm 99% sure this is not the right place to do this,
2706 * global_sid_Anonymous should probably be put into the token
2707 * instead of the guest id -- vl
2709 if (!lookup_sid(p->mem_ctx, &global_sid_Anonymous,
2710 &domname, &username, NULL)) {
2711 return NT_STATUS_NO_MEMORY;
2713 } else {
2714 username = p->session_info->unix_info->sanitized_username;
2715 domname = p->session_info->info->domain_name;
2718 account_name = talloc(p->mem_ctx, struct lsa_String);
2719 if (!account_name) {
2720 return NT_STATUS_NO_MEMORY;
2722 init_lsa_String(account_name, username);
2724 if (r->out.authority_name) {
2725 authority_name = talloc(p->mem_ctx, struct lsa_String);
2726 if (!authority_name) {
2727 return NT_STATUS_NO_MEMORY;
2729 init_lsa_String(authority_name, domname);
2732 *r->out.account_name = account_name;
2733 if (r->out.authority_name) {
2734 *r->out.authority_name = authority_name;
2737 return NT_STATUS_OK;
2740 /***************************************************************************
2741 _lsa_CreateAccount
2742 ***************************************************************************/
2744 NTSTATUS _lsa_CreateAccount(struct pipes_struct *p,
2745 struct lsa_CreateAccount *r)
2747 NTSTATUS status;
2748 struct lsa_info *handle;
2749 uint32_t acc_granted;
2750 struct security_descriptor *psd;
2751 size_t sd_size;
2752 uint32_t owner_access = (LSA_ACCOUNT_ALL_ACCESS &
2753 ~(LSA_ACCOUNT_ADJUST_PRIVILEGES|
2754 LSA_ACCOUNT_ADJUST_SYSTEM_ACCESS|
2755 SEC_STD_DELETE));
2757 /* find the connection policy handle. */
2758 if (!find_policy_by_hnd(p, r->in.handle, (void **)(void *)&handle))
2759 return NT_STATUS_INVALID_HANDLE;
2761 if (handle->type != LSA_HANDLE_POLICY_TYPE) {
2762 return NT_STATUS_INVALID_HANDLE;
2765 /* check if the user has enough rights */
2767 if (!(handle->access & LSA_POLICY_CREATE_ACCOUNT)) {
2768 return NT_STATUS_ACCESS_DENIED;
2771 /* Work out max allowed. */
2772 map_max_allowed_access(p->session_info->security_token,
2773 p->session_info->unix_token,
2774 &r->in.access_mask);
2776 /* map the generic bits to the lsa policy ones */
2777 se_map_generic(&r->in.access_mask, &lsa_account_mapping);
2779 status = make_lsa_object_sd(p->mem_ctx, &psd, &sd_size,
2780 &lsa_account_mapping,
2781 r->in.sid, owner_access);
2782 if (!NT_STATUS_IS_OK(status)) {
2783 return status;
2786 status = access_check_object(psd, p->session_info->security_token,
2787 SEC_PRIV_INVALID, SEC_PRIV_INVALID, 0, r->in.access_mask,
2788 &acc_granted, "_lsa_CreateAccount");
2789 if (!NT_STATUS_IS_OK(status)) {
2790 return status;
2793 if ( is_privileged_sid( r->in.sid ) )
2794 return NT_STATUS_OBJECT_NAME_COLLISION;
2796 status = create_lsa_policy_handle(p->mem_ctx, p,
2797 LSA_HANDLE_ACCOUNT_TYPE,
2798 acc_granted,
2799 r->in.sid,
2800 NULL,
2801 psd,
2802 r->out.acct_handle);
2803 if (!NT_STATUS_IS_OK(status)) {
2804 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2807 return privilege_create_account(r->in.sid);
2810 /***************************************************************************
2811 _lsa_OpenAccount
2812 ***************************************************************************/
2814 NTSTATUS _lsa_OpenAccount(struct pipes_struct *p,
2815 struct lsa_OpenAccount *r)
2817 struct lsa_info *handle;
2818 struct security_descriptor *psd = NULL;
2819 size_t sd_size;
2820 uint32_t des_access = r->in.access_mask;
2821 uint32_t acc_granted;
2822 uint32_t owner_access = (LSA_ACCOUNT_ALL_ACCESS &
2823 ~(LSA_ACCOUNT_ADJUST_PRIVILEGES|
2824 LSA_ACCOUNT_ADJUST_SYSTEM_ACCESS|
2825 SEC_STD_DELETE));
2826 NTSTATUS status;
2828 /* find the connection policy handle. */
2829 if (!find_policy_by_hnd(p, r->in.handle, (void **)(void *)&handle))
2830 return NT_STATUS_INVALID_HANDLE;
2832 if (handle->type != LSA_HANDLE_POLICY_TYPE) {
2833 return NT_STATUS_INVALID_HANDLE;
2836 /* des_access is for the account here, not the policy
2837 * handle - so don't check against policy handle. */
2839 /* Work out max allowed. */
2840 map_max_allowed_access(p->session_info->security_token,
2841 p->session_info->unix_token,
2842 &des_access);
2844 /* map the generic bits to the lsa account ones */
2845 se_map_generic(&des_access, &lsa_account_mapping);
2847 /* get the generic lsa account SD until we store it */
2848 status = make_lsa_object_sd(p->mem_ctx, &psd, &sd_size,
2849 &lsa_account_mapping,
2850 r->in.sid, owner_access);
2851 if (!NT_STATUS_IS_OK(status)) {
2852 return status;
2855 status = access_check_object(psd, p->session_info->security_token,
2856 SEC_PRIV_INVALID, SEC_PRIV_INVALID, 0, des_access,
2857 &acc_granted, "_lsa_OpenAccount" );
2858 if (!NT_STATUS_IS_OK(status)) {
2859 return status;
2862 /* TODO: Fis the parsing routine before reenabling this check! */
2863 #if 0
2864 if (!lookup_sid(&handle->sid, dom_name, name, &type))
2865 return NT_STATUS_ACCESS_DENIED;
2866 #endif
2868 status = create_lsa_policy_handle(p->mem_ctx, p,
2869 LSA_HANDLE_ACCOUNT_TYPE,
2870 acc_granted,
2871 r->in.sid,
2872 NULL,
2873 psd,
2874 r->out.acct_handle);
2875 if (!NT_STATUS_IS_OK(status)) {
2876 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2879 return NT_STATUS_OK;
2882 /***************************************************************************
2883 _lsa_EnumPrivsAccount
2884 For a given SID, enumerate all the privilege this account has.
2885 ***************************************************************************/
2887 NTSTATUS _lsa_EnumPrivsAccount(struct pipes_struct *p,
2888 struct lsa_EnumPrivsAccount *r)
2890 NTSTATUS status = NT_STATUS_OK;
2891 struct lsa_info *info=NULL;
2892 PRIVILEGE_SET *privileges;
2893 struct lsa_PrivilegeSet *priv_set = NULL;
2895 /* find the connection policy handle. */
2896 if (!find_policy_by_hnd(p, r->in.handle, (void **)(void *)&info))
2897 return NT_STATUS_INVALID_HANDLE;
2899 if (info->type != LSA_HANDLE_ACCOUNT_TYPE) {
2900 return NT_STATUS_INVALID_HANDLE;
2903 if (!(info->access & LSA_ACCOUNT_VIEW))
2904 return NT_STATUS_ACCESS_DENIED;
2906 status = get_privileges_for_sid_as_set(p->mem_ctx, &privileges, &info->sid);
2907 if (!NT_STATUS_IS_OK(status)) {
2908 return status;
2911 *r->out.privs = priv_set = talloc_zero(p->mem_ctx, struct lsa_PrivilegeSet);
2912 if (!priv_set) {
2913 return NT_STATUS_NO_MEMORY;
2916 DEBUG(10,("_lsa_EnumPrivsAccount: %s has %d privileges\n",
2917 sid_string_dbg(&info->sid),
2918 privileges->count));
2920 priv_set->count = privileges->count;
2921 priv_set->unknown = 0;
2922 priv_set->set = talloc_move(priv_set, &privileges->set);
2924 return status;
2927 /***************************************************************************
2928 _lsa_GetSystemAccessAccount
2929 ***************************************************************************/
2931 NTSTATUS _lsa_GetSystemAccessAccount(struct pipes_struct *p,
2932 struct lsa_GetSystemAccessAccount *r)
2934 NTSTATUS status;
2935 struct lsa_info *info = NULL;
2936 struct lsa_EnumPrivsAccount e;
2937 struct lsa_PrivilegeSet *privset;
2939 /* find the connection policy handle. */
2941 if (!find_policy_by_hnd(p, r->in.handle, (void **)(void *)&info))
2942 return NT_STATUS_INVALID_HANDLE;
2944 if (info->type != LSA_HANDLE_ACCOUNT_TYPE) {
2945 return NT_STATUS_INVALID_HANDLE;
2948 if (!(info->access & LSA_ACCOUNT_VIEW))
2949 return NT_STATUS_ACCESS_DENIED;
2951 privset = talloc_zero(p->mem_ctx, struct lsa_PrivilegeSet);
2952 if (!privset) {
2953 return NT_STATUS_NO_MEMORY;
2956 e.in.handle = r->in.handle;
2957 e.out.privs = &privset;
2959 status = _lsa_EnumPrivsAccount(p, &e);
2960 if (!NT_STATUS_IS_OK(status)) {
2961 DEBUG(10,("_lsa_GetSystemAccessAccount: "
2962 "failed to call _lsa_EnumPrivsAccount(): %s\n",
2963 nt_errstr(status)));
2964 return status;
2967 /* Samba4 would iterate over the privset to merge the policy mode bits,
2968 * not sure samba3 can do the same here, so just return what we did in
2969 * the past - gd */
2972 0x01 -> Log on locally
2973 0x02 -> Access this computer from network
2974 0x04 -> Log on as a batch job
2975 0x10 -> Log on as a service
2977 they can be ORed together
2980 *r->out.access_mask = LSA_POLICY_MODE_INTERACTIVE |
2981 LSA_POLICY_MODE_NETWORK;
2983 return NT_STATUS_OK;
2986 /***************************************************************************
2987 update the systemaccount information
2988 ***************************************************************************/
2990 NTSTATUS _lsa_SetSystemAccessAccount(struct pipes_struct *p,
2991 struct lsa_SetSystemAccessAccount *r)
2993 struct lsa_info *info=NULL;
2994 NTSTATUS status;
2995 GROUP_MAP *map;
2997 /* find the connection policy handle. */
2998 if (!find_policy_by_hnd(p, r->in.handle, (void **)(void *)&info))
2999 return NT_STATUS_INVALID_HANDLE;
3001 if (info->type != LSA_HANDLE_ACCOUNT_TYPE) {
3002 return NT_STATUS_INVALID_HANDLE;
3005 if (!(info->access & LSA_ACCOUNT_ADJUST_SYSTEM_ACCESS)) {
3006 return NT_STATUS_ACCESS_DENIED;
3009 map = talloc_zero(p->mem_ctx, GROUP_MAP);
3010 if (!map) {
3011 return NT_STATUS_NO_MEMORY;
3014 if (!pdb_getgrsid(map, info->sid)) {
3015 TALLOC_FREE(map);
3016 return NT_STATUS_NO_SUCH_GROUP;
3019 status = pdb_update_group_mapping_entry(map);
3020 TALLOC_FREE(map);
3021 return status;
3024 /***************************************************************************
3025 _lsa_AddPrivilegesToAccount
3026 For a given SID, add some privileges.
3027 ***************************************************************************/
3029 NTSTATUS _lsa_AddPrivilegesToAccount(struct pipes_struct *p,
3030 struct lsa_AddPrivilegesToAccount *r)
3032 struct lsa_info *info = NULL;
3033 struct lsa_PrivilegeSet *set = NULL;
3035 /* find the connection policy handle. */
3036 if (!find_policy_by_hnd(p, r->in.handle, (void **)(void *)&info))
3037 return NT_STATUS_INVALID_HANDLE;
3039 if (info->type != LSA_HANDLE_ACCOUNT_TYPE) {
3040 return NT_STATUS_INVALID_HANDLE;
3043 if (!(info->access & LSA_ACCOUNT_ADJUST_PRIVILEGES)) {
3044 return NT_STATUS_ACCESS_DENIED;
3047 set = r->in.privs;
3049 if ( !grant_privilege_set( &info->sid, set ) ) {
3050 DEBUG(3,("_lsa_AddPrivilegesToAccount: grant_privilege_set(%s) failed!\n",
3051 sid_string_dbg(&info->sid) ));
3052 return NT_STATUS_NO_SUCH_PRIVILEGE;
3055 return NT_STATUS_OK;
3058 /***************************************************************************
3059 _lsa_RemovePrivilegesFromAccount
3060 For a given SID, remove some privileges.
3061 ***************************************************************************/
3063 NTSTATUS _lsa_RemovePrivilegesFromAccount(struct pipes_struct *p,
3064 struct lsa_RemovePrivilegesFromAccount *r)
3066 struct lsa_info *info = NULL;
3067 struct lsa_PrivilegeSet *set = NULL;
3069 /* find the connection policy handle. */
3070 if (!find_policy_by_hnd(p, r->in.handle, (void **)(void *)&info))
3071 return NT_STATUS_INVALID_HANDLE;
3073 if (info->type != LSA_HANDLE_ACCOUNT_TYPE) {
3074 return NT_STATUS_INVALID_HANDLE;
3077 if (!(info->access & LSA_ACCOUNT_ADJUST_PRIVILEGES)) {
3078 return NT_STATUS_ACCESS_DENIED;
3081 set = r->in.privs;
3083 if ( !revoke_privilege_set( &info->sid, set) ) {
3084 DEBUG(3,("_lsa_RemovePrivilegesFromAccount: revoke_privilege(%s) failed!\n",
3085 sid_string_dbg(&info->sid) ));
3086 return NT_STATUS_NO_SUCH_PRIVILEGE;
3089 return NT_STATUS_OK;
3092 /***************************************************************************
3093 _lsa_LookupPrivName
3094 ***************************************************************************/
3096 NTSTATUS _lsa_LookupPrivName(struct pipes_struct *p,
3097 struct lsa_LookupPrivName *r)
3099 struct lsa_info *info = NULL;
3100 const char *name;
3101 struct lsa_StringLarge *lsa_name;
3103 /* find the connection policy handle. */
3104 if (!find_policy_by_hnd(p, r->in.handle, (void **)(void *)&info)) {
3105 return NT_STATUS_INVALID_HANDLE;
3108 if (info->type != LSA_HANDLE_POLICY_TYPE) {
3109 return NT_STATUS_INVALID_HANDLE;
3112 if (!(info->access & LSA_POLICY_VIEW_LOCAL_INFORMATION)) {
3113 return NT_STATUS_ACCESS_DENIED;
3116 if (r->in.luid->high != 0) {
3117 return NT_STATUS_NO_SUCH_PRIVILEGE;
3120 name = sec_privilege_name(r->in.luid->low);
3121 if (!name) {
3122 return NT_STATUS_NO_SUCH_PRIVILEGE;
3125 lsa_name = talloc_zero(p->mem_ctx, struct lsa_StringLarge);
3126 if (!lsa_name) {
3127 return NT_STATUS_NO_MEMORY;
3130 lsa_name->string = talloc_strdup(lsa_name, name);
3131 if (!lsa_name->string) {
3132 TALLOC_FREE(lsa_name);
3133 return NT_STATUS_NO_MEMORY;
3136 *r->out.name = lsa_name;
3138 return NT_STATUS_OK;
3141 /***************************************************************************
3142 _lsa_QuerySecurity
3143 ***************************************************************************/
3145 NTSTATUS _lsa_QuerySecurity(struct pipes_struct *p,
3146 struct lsa_QuerySecurity *r)
3148 struct lsa_info *handle=NULL;
3149 struct security_descriptor *psd = NULL;
3150 size_t sd_size = 0;
3151 NTSTATUS status;
3153 /* find the connection policy handle. */
3154 if (!find_policy_by_hnd(p, r->in.handle, (void **)(void *)&handle))
3155 return NT_STATUS_INVALID_HANDLE;
3157 switch (handle->type) {
3158 case LSA_HANDLE_POLICY_TYPE:
3159 case LSA_HANDLE_ACCOUNT_TYPE:
3160 case LSA_HANDLE_TRUST_TYPE:
3161 case LSA_HANDLE_SECRET_TYPE:
3162 psd = handle->sd;
3163 sd_size = ndr_size_security_descriptor(psd, 0);
3164 status = NT_STATUS_OK;
3165 break;
3166 default:
3167 status = NT_STATUS_INVALID_HANDLE;
3168 break;
3171 if (!NT_STATUS_IS_OK(status)) {
3172 return status;
3175 *r->out.sdbuf = make_sec_desc_buf(p->mem_ctx, sd_size, psd);
3176 if (!*r->out.sdbuf) {
3177 return NT_STATUS_NO_MEMORY;
3180 return status;
3183 /***************************************************************************
3184 _lsa_AddAccountRights
3185 ***************************************************************************/
3187 NTSTATUS _lsa_AddAccountRights(struct pipes_struct *p,
3188 struct lsa_AddAccountRights *r)
3190 struct lsa_info *info = NULL;
3191 int i = 0;
3192 uint32_t acc_granted = 0;
3193 struct security_descriptor *psd = NULL;
3194 size_t sd_size;
3195 struct dom_sid sid;
3196 NTSTATUS status;
3198 /* find the connection policy handle. */
3199 if (!find_policy_by_hnd(p, r->in.handle, (void **)(void *)&info))
3200 return NT_STATUS_INVALID_HANDLE;
3202 if (info->type != LSA_HANDLE_POLICY_TYPE) {
3203 return NT_STATUS_INVALID_HANDLE;
3206 /* get the generic lsa account SD for this SID until we store it */
3207 status = make_lsa_object_sd(p->mem_ctx, &psd, &sd_size,
3208 &lsa_account_mapping,
3209 NULL, 0);
3210 if (!NT_STATUS_IS_OK(status)) {
3211 return status;
3215 * From the MS DOCs. If the sid doesn't exist, ask for LSA_POLICY_CREATE_ACCOUNT
3216 * on the policy handle. If it does, ask for
3217 * LSA_ACCOUNT_ADJUST_PRIVILEGES|LSA_ACCOUNT_ADJUST_SYSTEM_ACCESS|LSA_ACCOUNT_VIEW,
3218 * on the account sid. We don't check here so just use the latter. JRA.
3221 status = access_check_object(psd, p->session_info->security_token,
3222 SEC_PRIV_INVALID, SEC_PRIV_INVALID, 0,
3223 LSA_ACCOUNT_ADJUST_PRIVILEGES|LSA_ACCOUNT_ADJUST_SYSTEM_ACCESS|LSA_ACCOUNT_VIEW,
3224 &acc_granted, "_lsa_AddAccountRights" );
3225 if (!NT_STATUS_IS_OK(status)) {
3226 return status;
3229 /* according to an NT4 PDC, you can add privileges to SIDs even without
3230 call_lsa_create_account() first. And you can use any arbitrary SID. */
3232 sid_copy( &sid, r->in.sid );
3234 for ( i=0; i < r->in.rights->count; i++ ) {
3236 const char *privname = r->in.rights->names[i].string;
3238 /* only try to add non-null strings */
3240 if ( !privname )
3241 continue;
3243 if ( !grant_privilege_by_name( &sid, privname ) ) {
3244 DEBUG(2,("_lsa_AddAccountRights: Failed to add privilege [%s]\n",
3245 privname ));
3246 return NT_STATUS_NO_SUCH_PRIVILEGE;
3250 return NT_STATUS_OK;
3253 /***************************************************************************
3254 _lsa_RemoveAccountRights
3255 ***************************************************************************/
3257 NTSTATUS _lsa_RemoveAccountRights(struct pipes_struct *p,
3258 struct lsa_RemoveAccountRights *r)
3260 struct lsa_info *info = NULL;
3261 int i = 0;
3262 struct security_descriptor *psd = NULL;
3263 size_t sd_size;
3264 struct dom_sid sid;
3265 const char *privname = NULL;
3266 uint32_t acc_granted = 0;
3267 NTSTATUS status;
3269 /* find the connection policy handle. */
3270 if (!find_policy_by_hnd(p, r->in.handle, (void **)(void *)&info))
3271 return NT_STATUS_INVALID_HANDLE;
3273 if (info->type != LSA_HANDLE_POLICY_TYPE) {
3274 return NT_STATUS_INVALID_HANDLE;
3277 /* get the generic lsa account SD for this SID until we store it */
3278 status = make_lsa_object_sd(p->mem_ctx, &psd, &sd_size,
3279 &lsa_account_mapping,
3280 NULL, 0);
3281 if (!NT_STATUS_IS_OK(status)) {
3282 return status;
3286 * From the MS DOCs. We need
3287 * LSA_ACCOUNT_ADJUST_PRIVILEGES|LSA_ACCOUNT_ADJUST_SYSTEM_ACCESS|LSA_ACCOUNT_VIEW
3288 * and DELETE on the account sid.
3291 status = access_check_object(psd, p->session_info->security_token,
3292 SEC_PRIV_INVALID, SEC_PRIV_INVALID, 0,
3293 LSA_ACCOUNT_ADJUST_PRIVILEGES|LSA_ACCOUNT_ADJUST_SYSTEM_ACCESS|
3294 LSA_ACCOUNT_VIEW|SEC_STD_DELETE,
3295 &acc_granted, "_lsa_RemoveAccountRights");
3296 if (!NT_STATUS_IS_OK(status)) {
3297 return status;
3300 sid_copy( &sid, r->in.sid );
3302 if ( r->in.remove_all ) {
3303 if ( !revoke_all_privileges( &sid ) )
3304 return NT_STATUS_ACCESS_DENIED;
3306 return NT_STATUS_OK;
3309 for ( i=0; i < r->in.rights->count; i++ ) {
3311 privname = r->in.rights->names[i].string;
3313 /* only try to add non-null strings */
3315 if ( !privname )
3316 continue;
3318 if ( !revoke_privilege_by_name( &sid, privname ) ) {
3319 DEBUG(2,("_lsa_RemoveAccountRights: Failed to revoke privilege [%s]\n",
3320 privname ));
3321 return NT_STATUS_NO_SUCH_PRIVILEGE;
3325 return NT_STATUS_OK;
3328 /*******************************************************************
3329 ********************************************************************/
3331 static NTSTATUS init_lsa_right_set(TALLOC_CTX *mem_ctx,
3332 struct lsa_RightSet *r,
3333 PRIVILEGE_SET *privileges)
3335 uint32 i;
3336 const char *privname;
3337 const char **privname_array = NULL;
3338 int num_priv = 0;
3340 for (i=0; i<privileges->count; i++) {
3341 if (privileges->set[i].luid.high) {
3342 continue;
3344 privname = sec_privilege_name(privileges->set[i].luid.low);
3345 if (privname) {
3346 if (!add_string_to_array(mem_ctx, privname,
3347 &privname_array, &num_priv)) {
3348 return NT_STATUS_NO_MEMORY;
3353 if (num_priv) {
3355 r->names = talloc_zero_array(mem_ctx, struct lsa_StringLarge,
3356 num_priv);
3357 if (!r->names) {
3358 return NT_STATUS_NO_MEMORY;
3361 for (i=0; i<num_priv; i++) {
3362 init_lsa_StringLarge(&r->names[i], privname_array[i]);
3365 r->count = num_priv;
3368 return NT_STATUS_OK;
3371 /***************************************************************************
3372 _lsa_EnumAccountRights
3373 ***************************************************************************/
3375 NTSTATUS _lsa_EnumAccountRights(struct pipes_struct *p,
3376 struct lsa_EnumAccountRights *r)
3378 NTSTATUS status;
3379 struct lsa_info *info = NULL;
3380 PRIVILEGE_SET *privileges;
3382 /* find the connection policy handle. */
3384 if (!find_policy_by_hnd(p, r->in.handle, (void **)(void *)&info))
3385 return NT_STATUS_INVALID_HANDLE;
3387 if (info->type != LSA_HANDLE_POLICY_TYPE) {
3388 return NT_STATUS_INVALID_HANDLE;
3391 if (!(info->access & LSA_ACCOUNT_VIEW)) {
3392 return NT_STATUS_ACCESS_DENIED;
3395 /* according to an NT4 PDC, you can add privileges to SIDs even without
3396 call_lsa_create_account() first. And you can use any arbitrary SID. */
3398 /* according to MS-LSAD 3.1.4.5.10 it is required to return
3399 * NT_STATUS_OBJECT_NAME_NOT_FOUND if the account sid was not found in
3400 * the lsa database */
3402 status = get_privileges_for_sid_as_set(p->mem_ctx, &privileges, r->in.sid);
3403 if (!NT_STATUS_IS_OK(status)) {
3404 return status;
3407 DEBUG(10,("_lsa_EnumAccountRights: %s has %d privileges\n",
3408 sid_string_dbg(r->in.sid), privileges->count));
3410 status = init_lsa_right_set(p->mem_ctx, r->out.rights, privileges);
3412 return status;
3415 /***************************************************************************
3416 _lsa_LookupPrivValue
3417 ***************************************************************************/
3419 NTSTATUS _lsa_LookupPrivValue(struct pipes_struct *p,
3420 struct lsa_LookupPrivValue *r)
3422 struct lsa_info *info = NULL;
3423 const char *name = NULL;
3425 /* find the connection policy handle. */
3427 if (!find_policy_by_hnd(p, r->in.handle, (void **)(void *)&info))
3428 return NT_STATUS_INVALID_HANDLE;
3430 if (info->type != LSA_HANDLE_POLICY_TYPE) {
3431 return NT_STATUS_INVALID_HANDLE;
3434 if (!(info->access & LSA_POLICY_LOOKUP_NAMES))
3435 return NT_STATUS_ACCESS_DENIED;
3437 name = r->in.name->string;
3439 DEBUG(10,("_lsa_lookup_priv_value: name = %s\n", name));
3441 r->out.luid->low = sec_privilege_id(name);
3442 r->out.luid->high = 0;
3443 if (r->out.luid->low == SEC_PRIV_INVALID) {
3444 return NT_STATUS_NO_SUCH_PRIVILEGE;
3446 return NT_STATUS_OK;
3449 /***************************************************************************
3450 _lsa_EnumAccountsWithUserRight
3451 ***************************************************************************/
3453 NTSTATUS _lsa_EnumAccountsWithUserRight(struct pipes_struct *p,
3454 struct lsa_EnumAccountsWithUserRight *r)
3456 NTSTATUS status;
3457 struct lsa_info *info = NULL;
3458 struct dom_sid *sids = NULL;
3459 int num_sids = 0;
3460 uint32_t i;
3461 enum sec_privilege privilege;
3463 if (!find_policy_by_hnd(p, r->in.handle, (void **)(void *)&info)) {
3464 return NT_STATUS_INVALID_HANDLE;
3467 if (info->type != LSA_HANDLE_POLICY_TYPE) {
3468 return NT_STATUS_INVALID_HANDLE;
3471 if (!(info->access & LSA_POLICY_LOOKUP_NAMES)) {
3472 return NT_STATUS_ACCESS_DENIED;
3475 if (!r->in.name || !r->in.name->string) {
3476 return NT_STATUS_NO_SUCH_PRIVILEGE;
3479 privilege = sec_privilege_id(r->in.name->string);
3480 if (privilege == SEC_PRIV_INVALID) {
3481 return NT_STATUS_NO_SUCH_PRIVILEGE;
3484 status = privilege_enum_sids(privilege, p->mem_ctx,
3485 &sids, &num_sids);
3486 if (!NT_STATUS_IS_OK(status)) {
3487 return status;
3490 r->out.sids->num_sids = num_sids;
3491 r->out.sids->sids = talloc_array(p->mem_ctx, struct lsa_SidPtr,
3492 r->out.sids->num_sids);
3494 for (i=0; i < r->out.sids->num_sids; i++) {
3495 r->out.sids->sids[i].sid = dom_sid_dup(r->out.sids->sids,
3496 &sids[i]);
3497 if (!r->out.sids->sids[i].sid) {
3498 TALLOC_FREE(r->out.sids->sids);
3499 r->out.sids->num_sids = 0;
3500 return NT_STATUS_NO_MEMORY;
3504 return NT_STATUS_OK;
3507 /***************************************************************************
3508 _lsa_Delete
3509 ***************************************************************************/
3511 NTSTATUS _lsa_Delete(struct pipes_struct *p,
3512 struct lsa_Delete *r)
3514 return NT_STATUS_NOT_SUPPORTED;
3517 static NTSTATUS info_ex_2_pdb_trusted_domain(
3518 struct lsa_TrustDomainInfoInfoEx *info_ex,
3519 struct pdb_trusted_domain *td)
3521 if (info_ex->domain_name.string == NULL ||
3522 info_ex->netbios_name.string == NULL ||
3523 info_ex->sid == NULL) {
3524 return NT_STATUS_INVALID_PARAMETER;
3527 td->domain_name = talloc_strdup(td, info_ex->domain_name.string);
3528 td->netbios_name = talloc_strdup(td, info_ex->netbios_name.string);
3529 sid_copy(&td->security_identifier, info_ex->sid);
3530 if (td->domain_name == NULL ||
3531 td->netbios_name == NULL ||
3532 is_null_sid(&td->security_identifier)) {
3533 return NT_STATUS_NO_MEMORY;
3535 td->trust_direction = info_ex->trust_direction;
3536 td->trust_type = info_ex->trust_type;
3537 td->trust_attributes = info_ex->trust_attributes;
3539 return NT_STATUS_OK;
3542 static NTSTATUS setInfoTrustedDomain_base(struct pipes_struct *p,
3543 TALLOC_CTX *mem_ctx,
3544 struct lsa_info *policy,
3545 enum lsa_TrustDomInfoEnum level,
3546 union lsa_TrustedDomainInfo *info)
3548 struct lsa_TrustDomainInfoAuthInfoInternal *auth_info_int = NULL;
3549 DATA_BLOB auth_blob;
3550 struct trustDomainPasswords auth_struct;
3551 NTSTATUS nt_status;
3553 struct pdb_trusted_domain *td;
3554 struct pdb_trusted_domain *orig_td;
3556 td = talloc_zero(mem_ctx, struct pdb_trusted_domain);
3557 if (td == NULL) {
3558 return NT_STATUS_NO_MEMORY;
3561 switch (level) {
3562 case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
3563 if (!(policy->access & LSA_TRUSTED_SET_POSIX)) {
3564 return NT_STATUS_ACCESS_DENIED;
3566 td->trust_posix_offset = &info->posix_offset.posix_offset;
3567 break;
3568 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
3569 if (!(policy->access & LSA_TRUSTED_SET_POSIX)) {
3570 return NT_STATUS_ACCESS_DENIED;
3572 nt_status = info_ex_2_pdb_trusted_domain(&info->info_ex, td);
3573 if (!NT_STATUS_IS_OK(nt_status)) {
3574 return nt_status;
3576 break;
3577 case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO:
3578 if (!(policy->access & LSA_TRUSTED_SET_AUTH)) {
3579 return NT_STATUS_ACCESS_DENIED;
3581 nt_status = auth_info_2_auth_blob(td, &info->auth_info,
3582 &td->trust_auth_incoming,
3583 &td->trust_auth_outgoing);
3584 if (!NT_STATUS_IS_OK(nt_status)) {
3585 return nt_status;
3587 break;
3588 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
3589 if (!(policy->access & (LSA_TRUSTED_SET_AUTH | LSA_TRUSTED_SET_POSIX))) {
3590 return NT_STATUS_ACCESS_DENIED;
3592 td->trust_posix_offset = &info->full_info.posix_offset.posix_offset;
3593 nt_status = info_ex_2_pdb_trusted_domain(&info->full_info.info_ex,
3594 td);
3595 if (!NT_STATUS_IS_OK(nt_status)) {
3596 return nt_status;
3598 nt_status = auth_info_2_auth_blob(td,
3599 &info->full_info.auth_info,
3600 &td->trust_auth_incoming,
3601 &td->trust_auth_outgoing);
3602 if (!NT_STATUS_IS_OK(nt_status)) {
3603 return nt_status;
3605 break;
3606 case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO_INTERNAL:
3607 if (!(policy->access & LSA_TRUSTED_SET_AUTH)) {
3608 return NT_STATUS_ACCESS_DENIED;
3610 auth_info_int = &info->auth_info_internal;
3611 break;
3612 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_INTERNAL:
3613 if (!(policy->access & (LSA_TRUSTED_SET_AUTH | LSA_TRUSTED_SET_POSIX))) {
3614 return NT_STATUS_ACCESS_DENIED;
3616 td->trust_posix_offset = &info->full_info_internal.posix_offset.posix_offset;
3617 nt_status = info_ex_2_pdb_trusted_domain(&info->full_info_internal.info_ex,
3618 td);
3619 if (!NT_STATUS_IS_OK(nt_status)) {
3620 return nt_status;
3622 auth_info_int = &info->full_info_internal.auth_info;
3623 break;
3624 case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
3625 if (!(policy->access & LSA_TRUSTED_SET_POSIX)) {
3626 return NT_STATUS_ACCESS_DENIED;
3628 td->supported_enc_type = &info->enc_types.enc_types;
3629 break;
3630 default:
3631 return NT_STATUS_INVALID_PARAMETER;
3634 /* decode auth_info_int if set */
3635 if (auth_info_int) {
3637 /* now decrypt blob */
3638 auth_blob = data_blob_const(auth_info_int->auth_blob.data,
3639 auth_info_int->auth_blob.size);
3641 nt_status = get_trustdom_auth_blob(p, mem_ctx,
3642 &auth_blob, &auth_struct);
3643 if (!NT_STATUS_IS_OK(nt_status)) {
3644 return nt_status;
3646 } else {
3647 memset(&auth_struct, 0, sizeof(auth_struct));
3650 /* TODO: verify only one object matches the dns/netbios/sid triplet and that
3651 * this is the one we already have */
3653 /* TODO: check if the trust direction is changed and we need to add or remove
3654 * auth data */
3656 /* TODO: check if trust type shall be changed and return an error in this case
3657 * */
3658 nt_status = pdb_get_trusted_domain_by_sid(p->mem_ctx, &policy->sid,
3659 &orig_td);
3660 if (!NT_STATUS_IS_OK(nt_status)) {
3661 return nt_status;
3665 /* TODO: should we fetch previous values from the existing entry
3666 * and append them ? */
3667 if (auth_struct.incoming.count) {
3668 nt_status = get_trustauth_inout_blob(mem_ctx,
3669 &auth_struct.incoming,
3670 &td->trust_auth_incoming);
3671 if (!NT_STATUS_IS_OK(nt_status)) {
3672 return nt_status;
3674 } else {
3675 ZERO_STRUCT(td->trust_auth_incoming);
3678 if (auth_struct.outgoing.count) {
3679 nt_status = get_trustauth_inout_blob(mem_ctx,
3680 &auth_struct.outgoing,
3681 &td->trust_auth_outgoing);
3682 if (!NT_STATUS_IS_OK(nt_status)) {
3683 return nt_status;
3685 } else {
3686 ZERO_STRUCT(td->trust_auth_outgoing);
3689 nt_status = pdb_set_trusted_domain(orig_td->domain_name, td);
3690 if (!NT_STATUS_IS_OK(nt_status)) {
3691 return nt_status;
3694 return NT_STATUS_OK;
3697 NTSTATUS _lsa_SetTrustedDomainInfo(struct pipes_struct *p,
3698 struct lsa_SetTrustedDomainInfo *r)
3700 NTSTATUS status;
3701 struct policy_handle trustdom_handle;
3702 struct lsa_OpenTrustedDomain o;
3703 struct lsa_SetInformationTrustedDomain s;
3704 struct lsa_Close c;
3706 o.in.handle = r->in.handle;
3707 o.in.sid = r->in.dom_sid;
3708 o.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3709 o.out.trustdom_handle = &trustdom_handle;
3711 status = _lsa_OpenTrustedDomain(p, &o);
3712 if (!NT_STATUS_IS_OK(status)) {
3713 return status;
3716 s.in.trustdom_handle = &trustdom_handle;
3717 s.in.level = r->in.level;
3718 s.in.info = r->in.info;
3720 status = _lsa_SetInformationTrustedDomain(p, &s);
3721 if (!NT_STATUS_IS_OK(status)) {
3722 return status;
3725 c.in.handle = &trustdom_handle;
3726 c.out.handle = &trustdom_handle;
3728 return _lsa_Close(p, &c);
3731 NTSTATUS _lsa_SetTrustedDomainInfoByName(struct pipes_struct *p,
3732 struct lsa_SetTrustedDomainInfoByName *r)
3734 NTSTATUS status;
3735 struct policy_handle trustdom_handle;
3736 struct lsa_OpenTrustedDomainByName o;
3737 struct lsa_SetInformationTrustedDomain s;
3738 struct lsa_Close c;
3740 o.in.handle = r->in.handle;
3741 o.in.name.string = r->in.trusted_domain->string;
3742 o.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3743 o.out.trustdom_handle = &trustdom_handle;
3745 status = _lsa_OpenTrustedDomainByName(p, &o);
3746 if (!NT_STATUS_IS_OK(status)) {
3747 if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_DOMAIN)) {
3748 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3750 return status;
3753 s.in.trustdom_handle = &trustdom_handle;
3754 s.in.level = r->in.level;
3755 s.in.info = r->in.info;
3757 status = _lsa_SetInformationTrustedDomain(p, &s);
3758 if (!NT_STATUS_IS_OK(status)) {
3759 return status;
3762 c.in.handle = &trustdom_handle;
3763 c.out.handle = &trustdom_handle;
3765 return _lsa_Close(p, &c);
3768 NTSTATUS _lsa_SetInformationTrustedDomain(struct pipes_struct *p,
3769 struct lsa_SetInformationTrustedDomain *r)
3771 struct lsa_info *policy;
3773 if (!find_policy_by_hnd(p, r->in.trustdom_handle, (void **)(void *)&policy)) {
3774 return NT_STATUS_INVALID_HANDLE;
3777 if (policy->type != LSA_HANDLE_TRUST_TYPE) {
3778 return NT_STATUS_INVALID_HANDLE;
3781 return setInfoTrustedDomain_base(p, p->mem_ctx, policy,
3782 r->in.level, r->in.info);
3787 * From here on the server routines are just dummy ones to make smbd link with
3788 * librpc/gen_ndr/srv_lsa.c. These routines are actually never called, we are
3789 * pulling the server stubs across one by one.
3792 NTSTATUS _lsa_SetSecObj(struct pipes_struct *p, struct lsa_SetSecObj *r)
3794 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
3795 return NT_STATUS_NOT_IMPLEMENTED;
3798 NTSTATUS _lsa_ChangePassword(struct pipes_struct *p,
3799 struct lsa_ChangePassword *r)
3801 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
3802 return NT_STATUS_NOT_IMPLEMENTED;
3805 NTSTATUS _lsa_SetInfoPolicy(struct pipes_struct *p, struct lsa_SetInfoPolicy *r)
3807 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
3808 return NT_STATUS_NOT_IMPLEMENTED;
3811 NTSTATUS _lsa_ClearAuditLog(struct pipes_struct *p, struct lsa_ClearAuditLog *r)
3813 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
3814 return NT_STATUS_NOT_IMPLEMENTED;
3817 NTSTATUS _lsa_GetQuotasForAccount(struct pipes_struct *p,
3818 struct lsa_GetQuotasForAccount *r)
3820 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
3821 return NT_STATUS_NOT_IMPLEMENTED;
3824 NTSTATUS _lsa_SetQuotasForAccount(struct pipes_struct *p,
3825 struct lsa_SetQuotasForAccount *r)
3827 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
3828 return NT_STATUS_NOT_IMPLEMENTED;
3831 NTSTATUS _lsa_StorePrivateData(struct pipes_struct *p,
3832 struct lsa_StorePrivateData *r)
3834 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
3835 return NT_STATUS_NOT_IMPLEMENTED;
3838 NTSTATUS _lsa_RetrievePrivateData(struct pipes_struct *p,
3839 struct lsa_RetrievePrivateData *r)
3841 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
3842 return NT_STATUS_NOT_IMPLEMENTED;
3845 NTSTATUS _lsa_SetInfoPolicy2(struct pipes_struct *p,
3846 struct lsa_SetInfoPolicy2 *r)
3848 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
3849 return NT_STATUS_NOT_IMPLEMENTED;
3852 NTSTATUS _lsa_EnumTrustedDomainsEx(struct pipes_struct *p,
3853 struct lsa_EnumTrustedDomainsEx *r)
3855 struct lsa_info *info;
3856 uint32_t count;
3857 struct pdb_trusted_domain **domains;
3858 struct lsa_TrustDomainInfoInfoEx *entries;
3859 int i;
3860 NTSTATUS nt_status;
3862 /* bail out early if pdb backend is not capable of ex trusted domains,
3863 * if we dont do that, the client might not call
3864 * _lsa_EnumTrustedDomains() afterwards - gd */
3866 if (!(pdb_capabilities() & PDB_CAP_TRUSTED_DOMAINS_EX)) {
3867 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
3868 return NT_STATUS_NOT_IMPLEMENTED;
3871 if (!find_policy_by_hnd(p, r->in.handle, (void **)(void *)&info))
3872 return NT_STATUS_INVALID_HANDLE;
3874 if (info->type != LSA_HANDLE_POLICY_TYPE) {
3875 return NT_STATUS_INVALID_HANDLE;
3878 /* check if the user has enough rights */
3879 if (!(info->access & LSA_POLICY_VIEW_LOCAL_INFORMATION))
3880 return NT_STATUS_ACCESS_DENIED;
3882 become_root();
3883 nt_status = pdb_enum_trusted_domains(p->mem_ctx, &count, &domains);
3884 unbecome_root();
3886 if (!NT_STATUS_IS_OK(nt_status)) {
3887 return nt_status;
3890 entries = talloc_zero_array(p->mem_ctx, struct lsa_TrustDomainInfoInfoEx,
3891 count);
3892 if (!entries) {
3893 return NT_STATUS_NO_MEMORY;
3896 for (i=0; i<count; i++) {
3897 init_lsa_StringLarge(&entries[i].domain_name,
3898 domains[i]->domain_name);
3899 init_lsa_StringLarge(&entries[i].netbios_name,
3900 domains[i]->netbios_name);
3901 entries[i].sid = &domains[i]->security_identifier;
3902 entries[i].trust_direction = domains[i]->trust_direction;
3903 entries[i].trust_type = domains[i]->trust_type;
3904 entries[i].trust_attributes = domains[i]->trust_attributes;
3907 if (*r->in.resume_handle >= count) {
3908 *r->out.resume_handle = -1;
3909 TALLOC_FREE(entries);
3910 return NT_STATUS_NO_MORE_ENTRIES;
3913 /* return the rest, limit by max_size. Note that we
3914 use the w2k3 element size value of 60 */
3915 r->out.domains->count = count - *r->in.resume_handle;
3916 r->out.domains->count = MIN(r->out.domains->count,
3917 (r->in.max_size/LSA_ENUM_TRUST_DOMAIN_EX_MULTIPLIER));
3919 r->out.domains->domains = entries + *r->in.resume_handle;
3921 if (r->out.domains->count < count - *r->in.resume_handle) {
3922 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
3923 return STATUS_MORE_ENTRIES;
3926 /* according to MS-LSAD 3.1.4.7.8 output resume handle MUST
3927 * always be larger than the previous input resume handle, in
3928 * particular when hitting the last query it is vital to set the
3929 * resume handle correctly to avoid infinite client loops, as
3930 * seen e.g. with Windows XP SP3 when resume handle is 0 and
3931 * status is NT_STATUS_OK - gd */
3933 *r->out.resume_handle = (uint32_t)-1;
3935 return NT_STATUS_OK;
3938 NTSTATUS _lsa_QueryDomainInformationPolicy(struct pipes_struct *p,
3939 struct lsa_QueryDomainInformationPolicy *r)
3941 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
3942 return NT_STATUS_NOT_IMPLEMENTED;
3945 NTSTATUS _lsa_SetDomainInformationPolicy(struct pipes_struct *p,
3946 struct lsa_SetDomainInformationPolicy *r)
3948 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
3949 return NT_STATUS_NOT_IMPLEMENTED;
3952 NTSTATUS _lsa_TestCall(struct pipes_struct *p, struct lsa_TestCall *r)
3954 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
3955 return NT_STATUS_NOT_IMPLEMENTED;
3958 NTSTATUS _lsa_CREDRWRITE(struct pipes_struct *p, struct lsa_CREDRWRITE *r)
3960 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
3961 return NT_STATUS_NOT_IMPLEMENTED;
3964 NTSTATUS _lsa_CREDRREAD(struct pipes_struct *p, struct lsa_CREDRREAD *r)
3966 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
3967 return NT_STATUS_NOT_IMPLEMENTED;
3970 NTSTATUS _lsa_CREDRENUMERATE(struct pipes_struct *p, struct lsa_CREDRENUMERATE *r)
3972 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
3973 return NT_STATUS_NOT_IMPLEMENTED;
3976 NTSTATUS _lsa_CREDRWRITEDOMAINCREDENTIALS(struct pipes_struct *p,
3977 struct lsa_CREDRWRITEDOMAINCREDENTIALS *r)
3979 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
3980 return NT_STATUS_NOT_IMPLEMENTED;
3983 NTSTATUS _lsa_CREDRREADDOMAINCREDENTIALS(struct pipes_struct *p,
3984 struct lsa_CREDRREADDOMAINCREDENTIALS *r)
3986 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
3987 return NT_STATUS_NOT_IMPLEMENTED;
3990 NTSTATUS _lsa_CREDRDELETE(struct pipes_struct *p, struct lsa_CREDRDELETE *r)
3992 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
3993 return NT_STATUS_NOT_IMPLEMENTED;
3996 NTSTATUS _lsa_CREDRGETTARGETINFO(struct pipes_struct *p,
3997 struct lsa_CREDRGETTARGETINFO *r)
3999 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
4000 return NT_STATUS_NOT_IMPLEMENTED;
4003 NTSTATUS _lsa_CREDRPROFILELOADED(struct pipes_struct *p,
4004 struct lsa_CREDRPROFILELOADED *r)
4006 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
4007 return NT_STATUS_NOT_IMPLEMENTED;
4010 NTSTATUS _lsa_CREDRGETSESSIONTYPES(struct pipes_struct *p,
4011 struct lsa_CREDRGETSESSIONTYPES *r)
4013 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
4014 return NT_STATUS_NOT_IMPLEMENTED;
4017 NTSTATUS _lsa_LSARREGISTERAUDITEVENT(struct pipes_struct *p,
4018 struct lsa_LSARREGISTERAUDITEVENT *r)
4020 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
4021 return NT_STATUS_NOT_IMPLEMENTED;
4024 NTSTATUS _lsa_LSARGENAUDITEVENT(struct pipes_struct *p,
4025 struct lsa_LSARGENAUDITEVENT *r)
4027 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
4028 return NT_STATUS_NOT_IMPLEMENTED;
4031 NTSTATUS _lsa_LSARUNREGISTERAUDITEVENT(struct pipes_struct *p,
4032 struct lsa_LSARUNREGISTERAUDITEVENT *r)
4034 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
4035 return NT_STATUS_NOT_IMPLEMENTED;
4038 NTSTATUS _lsa_lsaRQueryForestTrustInformation(struct pipes_struct *p,
4039 struct lsa_lsaRQueryForestTrustInformation *r)
4041 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
4042 return NT_STATUS_NOT_IMPLEMENTED;
4045 #define DNS_CMP_MATCH 0
4046 #define DNS_CMP_FIRST_IS_CHILD 1
4047 #define DNS_CMP_SECOND_IS_CHILD 2
4048 #define DNS_CMP_NO_MATCH 3
4050 /* this function assumes names are well formed DNS names.
4051 * it doesn't validate them */
4052 static int dns_cmp(const char *s1, size_t l1,
4053 const char *s2, size_t l2)
4055 const char *p1, *p2;
4056 size_t t1, t2;
4057 int cret;
4059 if (l1 == l2) {
4060 if (strcasecmp_m(s1, s2) == 0) {
4061 return DNS_CMP_MATCH;
4063 return DNS_CMP_NO_MATCH;
4066 if (l1 > l2) {
4067 p1 = s1;
4068 p2 = s2;
4069 t1 = l1;
4070 t2 = l2;
4071 cret = DNS_CMP_FIRST_IS_CHILD;
4072 } else {
4073 p1 = s2;
4074 p2 = s1;
4075 t1 = l2;
4076 t2 = l1;
4077 cret = DNS_CMP_SECOND_IS_CHILD;
4080 if (p1[t1 - t2 - 1] != '.') {
4081 return DNS_CMP_NO_MATCH;
4084 if (strcasecmp_m(&p1[t1 - t2], p2) == 0) {
4085 return cret;
4088 return DNS_CMP_NO_MATCH;
4091 static NTSTATUS make_ft_info(TALLOC_CTX *mem_ctx,
4092 struct lsa_ForestTrustInformation *lfti,
4093 struct ForestTrustInfo *fti)
4095 struct lsa_ForestTrustRecord *lrec;
4096 struct ForestTrustInfoRecord *rec;
4097 struct lsa_StringLarge *tln;
4098 struct lsa_ForestTrustDomainInfo *info;
4099 uint32_t i;
4101 fti->version = 1;
4102 fti->count = lfti->count;
4103 fti->records = talloc_array(mem_ctx,
4104 struct ForestTrustInfoRecordArmor,
4105 fti->count);
4106 if (!fti->records) {
4107 return NT_STATUS_NO_MEMORY;
4109 for (i = 0; i < fti->count; i++) {
4110 lrec = lfti->entries[i];
4111 rec = &fti->records[i].record;
4113 rec->flags = lrec->flags;
4114 rec->timestamp = lrec->time;
4115 rec->type = lrec->type;
4117 switch (lrec->type) {
4118 case LSA_FOREST_TRUST_TOP_LEVEL_NAME:
4119 case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
4120 tln = &lrec->forest_trust_data.top_level_name;
4121 rec->data.name.string =
4122 talloc_strdup(mem_ctx, tln->string);
4123 if (!rec->data.name.string) {
4124 return NT_STATUS_NO_MEMORY;
4126 rec->data.name.size = strlen(rec->data.name.string);
4127 break;
4128 case LSA_FOREST_TRUST_DOMAIN_INFO:
4129 info = &lrec->forest_trust_data.domain_info;
4130 rec->data.info.sid = *info->domain_sid;
4131 rec->data.info.dns_name.string =
4132 talloc_strdup(mem_ctx,
4133 info->dns_domain_name.string);
4134 if (!rec->data.info.dns_name.string) {
4135 return NT_STATUS_NO_MEMORY;
4137 rec->data.info.dns_name.size =
4138 strlen(rec->data.info.dns_name.string);
4139 rec->data.info.netbios_name.string =
4140 talloc_strdup(mem_ctx,
4141 info->netbios_domain_name.string);
4142 if (!rec->data.info.netbios_name.string) {
4143 return NT_STATUS_NO_MEMORY;
4145 rec->data.info.netbios_name.size =
4146 strlen(rec->data.info.netbios_name.string);
4147 break;
4148 default:
4149 return NT_STATUS_INVALID_DOMAIN_STATE;
4153 return NT_STATUS_OK;
4156 static NTSTATUS add_collision(struct lsa_ForestTrustCollisionInfo *c_info,
4157 uint32_t index, uint32_t collision_type,
4158 uint32_t conflict_type, const char *tdo_name);
4160 static NTSTATUS check_ft_info(TALLOC_CTX *mem_ctx,
4161 const char *tdo_name,
4162 struct ForestTrustInfo *tdo_fti,
4163 struct ForestTrustInfo *new_fti,
4164 struct lsa_ForestTrustCollisionInfo *c_info)
4166 struct ForestTrustInfoRecord *nrec;
4167 struct ForestTrustInfoRecord *trec;
4168 const char *dns_name;
4169 const char *nb_name = NULL;
4170 struct dom_sid *sid = NULL;
4171 const char *tname = NULL;
4172 size_t dns_len = 0;
4173 size_t tlen = 0;
4174 uint32_t new_fti_idx;
4175 uint32_t i;
4176 /* use always TDO type, until we understand when Xref can be used */
4177 uint32_t collision_type = LSA_FOREST_TRUST_COLLISION_TDO;
4178 bool tln_conflict;
4179 bool sid_conflict;
4180 bool nb_conflict;
4181 bool exclusion;
4182 bool ex_rule = false;
4183 int ret;
4185 for (new_fti_idx = 0; new_fti_idx < new_fti->count; new_fti_idx++) {
4187 nrec = &new_fti->records[new_fti_idx].record;
4188 dns_name = NULL;
4189 tln_conflict = false;
4190 sid_conflict = false;
4191 nb_conflict = false;
4192 exclusion = false;
4194 switch (nrec->type) {
4195 case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
4196 /* exclusions do not conflict by definition */
4197 break;
4199 case FOREST_TRUST_TOP_LEVEL_NAME:
4200 dns_name = nrec->data.name.string;
4201 dns_len = nrec->data.name.size;
4202 break;
4204 case LSA_FOREST_TRUST_DOMAIN_INFO:
4205 dns_name = nrec->data.info.dns_name.string;
4206 dns_len = nrec->data.info.dns_name.size;
4207 nb_name = nrec->data.info.netbios_name.string;
4208 sid = &nrec->data.info.sid;
4209 break;
4212 if (!dns_name) continue;
4214 /* check if this is already taken and not excluded */
4215 for (i = 0; i < tdo_fti->count; i++) {
4216 trec = &tdo_fti->records[i].record;
4218 switch (trec->type) {
4219 case FOREST_TRUST_TOP_LEVEL_NAME:
4220 ex_rule = false;
4221 tname = trec->data.name.string;
4222 tlen = trec->data.name.size;
4223 break;
4224 case FOREST_TRUST_TOP_LEVEL_NAME_EX:
4225 ex_rule = true;
4226 tname = trec->data.name.string;
4227 tlen = trec->data.name.size;
4228 break;
4229 case FOREST_TRUST_DOMAIN_INFO:
4230 ex_rule = false;
4231 tname = trec->data.info.dns_name.string;
4232 tlen = trec->data.info.dns_name.size;
4233 break;
4234 default:
4235 return NT_STATUS_INVALID_PARAMETER;
4237 ret = dns_cmp(dns_name, dns_len, tname, tlen);
4238 switch (ret) {
4239 case DNS_CMP_MATCH:
4240 /* if it matches exclusion,
4241 * it doesn't conflict */
4242 if (ex_rule) {
4243 exclusion = true;
4244 break;
4246 /* fall through */
4247 case DNS_CMP_FIRST_IS_CHILD:
4248 case DNS_CMP_SECOND_IS_CHILD:
4249 tln_conflict = true;
4250 /* fall through */
4251 default:
4252 break;
4255 /* explicit exclusion, no dns name conflict here */
4256 if (exclusion) {
4257 tln_conflict = false;
4260 if (trec->type != FOREST_TRUST_DOMAIN_INFO) {
4261 continue;
4264 /* also test for domain info */
4265 if (!(trec->flags & LSA_SID_DISABLED_ADMIN) &&
4266 dom_sid_compare(&trec->data.info.sid, sid) == 0) {
4267 sid_conflict = true;
4269 if (!(trec->flags & LSA_NB_DISABLED_ADMIN) &&
4270 strcasecmp_m(trec->data.info.netbios_name.string,
4271 nb_name) == 0) {
4272 nb_conflict = true;
4276 if (tln_conflict) {
4277 (void)add_collision(c_info, new_fti_idx,
4278 collision_type,
4279 LSA_TLN_DISABLED_CONFLICT,
4280 tdo_name);
4282 if (sid_conflict) {
4283 (void)add_collision(c_info, new_fti_idx,
4284 collision_type,
4285 LSA_SID_DISABLED_CONFLICT,
4286 tdo_name);
4288 if (nb_conflict) {
4289 (void)add_collision(c_info, new_fti_idx,
4290 collision_type,
4291 LSA_NB_DISABLED_CONFLICT,
4292 tdo_name);
4296 return NT_STATUS_OK;
4299 static NTSTATUS add_collision(struct lsa_ForestTrustCollisionInfo *c_info,
4300 uint32_t idx, uint32_t collision_type,
4301 uint32_t conflict_type, const char *tdo_name)
4303 struct lsa_ForestTrustCollisionRecord **es;
4304 uint32_t i = c_info->count;
4306 es = talloc_realloc(c_info, c_info->entries,
4307 struct lsa_ForestTrustCollisionRecord *, i + 1);
4308 if (!es) {
4309 return NT_STATUS_NO_MEMORY;
4311 c_info->entries = es;
4312 c_info->count = i + 1;
4314 es[i] = talloc(es, struct lsa_ForestTrustCollisionRecord);
4315 if (!es[i]) {
4316 return NT_STATUS_NO_MEMORY;
4319 es[i]->index = idx;
4320 es[i]->type = collision_type;
4321 es[i]->flags.flags = conflict_type;
4322 es[i]->name.string = talloc_strdup(es[i], tdo_name);
4323 if (!es[i]->name.string) {
4324 return NT_STATUS_NO_MEMORY;
4326 es[i]->name.size = strlen(es[i]->name.string);
4328 return NT_STATUS_OK;
4331 static NTSTATUS get_ft_info(TALLOC_CTX *mem_ctx,
4332 struct pdb_trusted_domain *td,
4333 struct ForestTrustInfo *info)
4335 enum ndr_err_code ndr_err;
4337 if (td->trust_forest_trust_info.length == 0 ||
4338 td->trust_forest_trust_info.data == NULL) {
4339 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4341 ndr_err = ndr_pull_struct_blob_all(&td->trust_forest_trust_info, mem_ctx,
4342 info,
4343 (ndr_pull_flags_fn_t)ndr_pull_ForestTrustInfo);
4344 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
4345 return NT_STATUS_INVALID_DOMAIN_STATE;
4348 return NT_STATUS_OK;
4351 static NTSTATUS own_ft_info(struct pdb_domain_info *dom_info,
4352 struct ForestTrustInfo *fti)
4354 struct ForestTrustDataDomainInfo *info;
4355 struct ForestTrustInfoRecord *rec;
4357 fti->version = 1;
4358 fti->count = 2;
4359 fti->records = talloc_array(fti,
4360 struct ForestTrustInfoRecordArmor, 2);
4361 if (!fti->records) {
4362 return NT_STATUS_NO_MEMORY;
4365 /* TLN info */
4366 rec = &fti->records[0].record;
4368 rec->flags = 0;
4369 rec->timestamp = 0;
4370 rec->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
4372 rec->data.name.string = talloc_strdup(fti, dom_info->dns_forest);
4373 if (!rec->data.name.string) {
4374 return NT_STATUS_NO_MEMORY;
4376 rec->data.name.size = strlen(rec->data.name.string);
4378 /* DOMAIN info */
4379 rec = &fti->records[1].record;
4381 rec->flags = 0;
4382 rec->timestamp = 0;
4383 rec->type = LSA_FOREST_TRUST_DOMAIN_INFO;
4385 info = &rec->data.info;
4387 info->sid = dom_info->sid;
4388 info->dns_name.string = talloc_strdup(fti, dom_info->dns_domain);
4389 if (!info->dns_name.string) {
4390 return NT_STATUS_NO_MEMORY;
4392 info->dns_name.size = strlen(info->dns_name.string);
4393 info->netbios_name.string = talloc_strdup(fti, dom_info->name);
4394 if (!info->netbios_name.string) {
4395 return NT_STATUS_NO_MEMORY;
4397 info->netbios_name.size = strlen(info->netbios_name.string);
4399 return NT_STATUS_OK;
4402 NTSTATUS _lsa_lsaRSetForestTrustInformation(struct pipes_struct *p,
4403 struct lsa_lsaRSetForestTrustInformation *r)
4405 NTSTATUS status;
4406 int i;
4407 int j;
4408 struct lsa_info *handle;
4409 uint32_t num_domains;
4410 struct pdb_trusted_domain **domains;
4411 struct ForestTrustInfo *nfti;
4412 struct ForestTrustInfo *fti;
4413 struct lsa_ForestTrustCollisionInfo *c_info;
4414 struct pdb_domain_info *dom_info;
4415 enum ndr_err_code ndr_err;
4417 if (!IS_DC) {
4418 return NT_STATUS_NOT_SUPPORTED;
4421 if (!find_policy_by_hnd(p, r->in.handle, (void **)(void *)&handle)) {
4422 return NT_STATUS_INVALID_HANDLE;
4425 if (handle->type != LSA_HANDLE_TRUST_TYPE) {
4426 return NT_STATUS_INVALID_HANDLE;
4429 if (!(handle->access & LSA_TRUSTED_SET_AUTH)) {
4430 return NT_STATUS_ACCESS_DENIED;
4433 status = pdb_enum_trusted_domains(p->mem_ctx, &num_domains, &domains);
4434 if (!NT_STATUS_IS_OK(status)) {
4435 return status;
4437 if (num_domains == 0) {
4438 return NT_STATUS_NO_SUCH_DOMAIN;
4441 for (i = 0; i < num_domains; i++) {
4442 if (domains[i]->domain_name == NULL) {
4443 return NT_STATUS_INVALID_DOMAIN_STATE;
4445 if (strcasecmp_m(domains[i]->domain_name,
4446 r->in.trusted_domain_name->string) == 0) {
4447 break;
4450 if (i >= num_domains) {
4451 return NT_STATUS_NO_SUCH_DOMAIN;
4454 if (!(domains[i]->trust_attributes &
4455 LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
4456 return NT_STATUS_INVALID_PARAMETER;
4459 if (r->in.highest_record_type >= LSA_FOREST_TRUST_RECORD_TYPE_LAST) {
4460 return NT_STATUS_INVALID_PARAMETER;
4463 /* The following section until COPY_END is a copy from
4464 * source4/rpmc_server/lsa/scesrc_lsa.c */
4465 nfti = talloc(p->mem_ctx, struct ForestTrustInfo);
4466 if (!nfti) {
4467 return NT_STATUS_NO_MEMORY;
4470 status = make_ft_info(nfti, r->in.forest_trust_info, nfti);
4471 if (!NT_STATUS_IS_OK(status)) {
4472 return status;
4475 c_info = talloc_zero(r->out.collision_info,
4476 struct lsa_ForestTrustCollisionInfo);
4477 if (!c_info) {
4478 return NT_STATUS_NO_MEMORY;
4481 /* first check own info, then other domains */
4482 fti = talloc(p->mem_ctx, struct ForestTrustInfo);
4483 if (!fti) {
4484 return NT_STATUS_NO_MEMORY;
4487 dom_info = pdb_get_domain_info(p->mem_ctx);
4489 status = own_ft_info(dom_info, fti);
4490 if (!NT_STATUS_IS_OK(status)) {
4491 return status;
4494 status = check_ft_info(c_info, dom_info->dns_domain, fti, nfti, c_info);
4495 if (!NT_STATUS_IS_OK(status)) {
4496 return status;
4499 for (j = 0; j < num_domains; j++) {
4500 fti = talloc(p->mem_ctx, struct ForestTrustInfo);
4501 if (!fti) {
4502 return NT_STATUS_NO_MEMORY;
4505 status = get_ft_info(p->mem_ctx, domains[j], fti);
4506 if (!NT_STATUS_IS_OK(status)) {
4507 if (NT_STATUS_EQUAL(status,
4508 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4509 continue;
4511 return status;
4514 if (domains[j]->domain_name == NULL) {
4515 return NT_STATUS_INVALID_DOMAIN_STATE;
4518 status = check_ft_info(c_info, domains[j]->domain_name,
4519 fti, nfti, c_info);
4520 if (!NT_STATUS_IS_OK(status)) {
4521 return status;
4525 *r->out.collision_info = c_info;
4527 if (r->in.check_only != 0) {
4528 return NT_STATUS_OK;
4531 /* COPY_END */
4533 ndr_err = ndr_push_struct_blob(&domains[i]->trust_forest_trust_info,
4534 p->mem_ctx, nfti,
4535 (ndr_push_flags_fn_t)ndr_push_ForestTrustInfo);
4536 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
4537 return NT_STATUS_INVALID_PARAMETER;
4540 status = pdb_set_trusted_domain(domains[i]->domain_name, domains[i]);
4541 if (!NT_STATUS_IS_OK(status)) {
4542 return status;
4545 return NT_STATUS_OK;
4548 NTSTATUS _lsa_CREDRRENAME(struct pipes_struct *p,
4549 struct lsa_CREDRRENAME *r)
4551 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
4552 return NT_STATUS_NOT_IMPLEMENTED;
4555 NTSTATUS _lsa_LSAROPENPOLICYSCE(struct pipes_struct *p,
4556 struct lsa_LSAROPENPOLICYSCE *r)
4558 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
4559 return NT_STATUS_NOT_IMPLEMENTED;
4562 NTSTATUS _lsa_LSARADTREGISTERSECURITYEVENTSOURCE(struct pipes_struct *p,
4563 struct lsa_LSARADTREGISTERSECURITYEVENTSOURCE *r)
4565 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
4566 return NT_STATUS_NOT_IMPLEMENTED;
4569 NTSTATUS _lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE(struct pipes_struct *p,
4570 struct lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE *r)
4572 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
4573 return NT_STATUS_NOT_IMPLEMENTED;
4576 NTSTATUS _lsa_LSARADTREPORTSECURITYEVENT(struct pipes_struct *p,
4577 struct lsa_LSARADTREPORTSECURITYEVENT *r)
4579 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
4580 return NT_STATUS_NOT_IMPLEMENTED;