auth and s4-rpc_server: Do not use features we currently can't implement with MIT...
[Samba/gebeck_regimport.git] / source4 / rpc_server / lsa / dcesrv_lsa.c
blobf1b8740078e45d827a736d907af70073469a7bd1
1 /* need access mask/acl implementation */
3 /*
4 Unix SMB/CIFS implementation.
6 endpoint server for the lsarpc pipe
8 Copyright (C) Andrew Tridgell 2004
9 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2008
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 3 of the License, or
14 (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program. If not, see <http://www.gnu.org/licenses/>.
25 #include "rpc_server/lsa/lsa.h"
26 #include "system/kerberos.h"
27 #include "auth/kerberos/kerberos.h"
28 #include "librpc/gen_ndr/ndr_drsblobs.h"
29 #include "librpc/gen_ndr/ndr_lsa.h"
30 #include "../lib/crypto/crypto.h"
31 #include "lib/util/tsort.h"
32 #include "dsdb/common/util.h"
33 #include "libcli/security/session.h"
34 #include "libcli/lsarpc/util_lsarpc.h"
37 this type allows us to distinguish handle types
41 state associated with a lsa_OpenAccount() operation
43 struct lsa_account_state {
44 struct lsa_policy_state *policy;
45 uint32_t access_mask;
46 struct dom_sid *account_sid;
51 state associated with a lsa_OpenSecret() operation
53 struct lsa_secret_state {
54 struct lsa_policy_state *policy;
55 uint32_t access_mask;
56 struct ldb_dn *secret_dn;
57 struct ldb_context *sam_ldb;
58 bool global;
62 state associated with a lsa_OpenTrustedDomain() operation
64 struct lsa_trusted_domain_state {
65 struct lsa_policy_state *policy;
66 uint32_t access_mask;
67 struct ldb_dn *trusted_domain_dn;
68 struct ldb_dn *trusted_domain_user_dn;
72 this is based on the samba3 function make_lsa_object_sd()
73 It uses the same logic, but with samba4 helper functions
75 static NTSTATUS dcesrv_build_lsa_sd(TALLOC_CTX *mem_ctx,
76 struct security_descriptor **sd,
77 struct dom_sid *sid,
78 uint32_t sid_access)
80 NTSTATUS status;
81 uint32_t rid;
82 struct dom_sid *domain_sid, *domain_admins_sid;
83 const char *domain_admins_sid_str, *sidstr;
84 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
86 status = dom_sid_split_rid(tmp_ctx, sid, &domain_sid, &rid);
87 NT_STATUS_NOT_OK_RETURN_AND_FREE(status, tmp_ctx);
89 domain_admins_sid = dom_sid_add_rid(tmp_ctx, domain_sid, DOMAIN_RID_ADMINS);
90 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(domain_admins_sid, tmp_ctx);
92 domain_admins_sid_str = dom_sid_string(tmp_ctx, domain_admins_sid);
93 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(domain_admins_sid_str, tmp_ctx);
95 sidstr = dom_sid_string(tmp_ctx, sid);
96 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sidstr, tmp_ctx);
98 *sd = security_descriptor_dacl_create(mem_ctx,
99 0, sidstr, NULL,
101 SID_WORLD,
102 SEC_ACE_TYPE_ACCESS_ALLOWED,
103 SEC_GENERIC_EXECUTE | SEC_GENERIC_READ, 0,
105 SID_BUILTIN_ADMINISTRATORS,
106 SEC_ACE_TYPE_ACCESS_ALLOWED,
107 SEC_GENERIC_ALL, 0,
109 SID_BUILTIN_ACCOUNT_OPERATORS,
110 SEC_ACE_TYPE_ACCESS_ALLOWED,
111 SEC_GENERIC_ALL, 0,
113 domain_admins_sid_str,
114 SEC_ACE_TYPE_ACCESS_ALLOWED,
115 SEC_GENERIC_ALL, 0,
117 sidstr,
118 SEC_ACE_TYPE_ACCESS_ALLOWED,
119 sid_access, 0,
121 NULL);
122 talloc_free(tmp_ctx);
124 NT_STATUS_HAVE_NO_MEMORY(*sd);
126 return NT_STATUS_OK;
130 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call,
131 TALLOC_CTX *mem_ctx,
132 struct lsa_EnumAccountRights *r);
134 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
135 TALLOC_CTX *mem_ctx,
136 struct lsa_policy_state *state,
137 int ldb_flag,
138 struct dom_sid *sid,
139 const struct lsa_RightSet *rights);
142 lsa_Close
144 static NTSTATUS dcesrv_lsa_Close(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
145 struct lsa_Close *r)
147 struct dcesrv_handle *h;
149 *r->out.handle = *r->in.handle;
151 DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
153 talloc_free(h);
155 ZERO_STRUCTP(r->out.handle);
157 return NT_STATUS_OK;
162 lsa_Delete
164 static NTSTATUS dcesrv_lsa_Delete(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
165 struct lsa_Delete *r)
167 return NT_STATUS_NOT_SUPPORTED;
172 lsa_DeleteObject
174 static NTSTATUS dcesrv_lsa_DeleteObject(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
175 struct lsa_DeleteObject *r)
177 struct dcesrv_handle *h;
178 int ret;
180 DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
182 if (h->wire_handle.handle_type == LSA_HANDLE_SECRET) {
183 struct lsa_secret_state *secret_state = h->data;
185 /* Ensure user is permitted to delete this... */
186 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
188 case SECURITY_SYSTEM:
189 case SECURITY_ADMINISTRATOR:
190 break;
191 default:
192 /* Users and anonymous are not allowed to delete things */
193 return NT_STATUS_ACCESS_DENIED;
196 ret = ldb_delete(secret_state->sam_ldb,
197 secret_state->secret_dn);
198 if (ret != LDB_SUCCESS) {
199 return NT_STATUS_INVALID_HANDLE;
202 ZERO_STRUCTP(r->out.handle);
204 return NT_STATUS_OK;
206 } else if (h->wire_handle.handle_type == LSA_HANDLE_TRUSTED_DOMAIN) {
207 struct lsa_trusted_domain_state *trusted_domain_state =
208 talloc_get_type(h->data, struct lsa_trusted_domain_state);
209 ret = ldb_transaction_start(trusted_domain_state->policy->sam_ldb);
210 if (ret != LDB_SUCCESS) {
211 return NT_STATUS_INTERNAL_DB_CORRUPTION;
214 ret = ldb_delete(trusted_domain_state->policy->sam_ldb,
215 trusted_domain_state->trusted_domain_dn);
216 if (ret != LDB_SUCCESS) {
217 ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
218 return NT_STATUS_INVALID_HANDLE;
221 if (trusted_domain_state->trusted_domain_user_dn) {
222 ret = ldb_delete(trusted_domain_state->policy->sam_ldb,
223 trusted_domain_state->trusted_domain_user_dn);
224 if (ret != LDB_SUCCESS) {
225 ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
226 return NT_STATUS_INVALID_HANDLE;
230 ret = ldb_transaction_commit(trusted_domain_state->policy->sam_ldb);
231 if (ret != LDB_SUCCESS) {
232 return NT_STATUS_INTERNAL_DB_CORRUPTION;
235 ZERO_STRUCTP(r->out.handle);
237 return NT_STATUS_OK;
239 } else if (h->wire_handle.handle_type == LSA_HANDLE_ACCOUNT) {
240 struct lsa_RightSet *rights;
241 struct lsa_account_state *astate;
242 struct lsa_EnumAccountRights r2;
243 NTSTATUS status;
245 rights = talloc(mem_ctx, struct lsa_RightSet);
247 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
249 astate = h->data;
251 r2.in.handle = &astate->policy->handle->wire_handle;
252 r2.in.sid = astate->account_sid;
253 r2.out.rights = rights;
255 /* dcesrv_lsa_EnumAccountRights takes a LSA_HANDLE_POLICY,
256 but we have a LSA_HANDLE_ACCOUNT here, so this call
257 will always fail */
258 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
259 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
260 return NT_STATUS_OK;
263 if (!NT_STATUS_IS_OK(status)) {
264 return status;
267 status = dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
268 LDB_FLAG_MOD_DELETE, astate->account_sid,
269 r2.out.rights);
270 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
271 return NT_STATUS_OK;
274 if (!NT_STATUS_IS_OK(status)) {
275 return status;
278 ZERO_STRUCTP(r->out.handle);
280 return NT_STATUS_OK;
283 return NT_STATUS_INVALID_HANDLE;
288 lsa_EnumPrivs
290 static NTSTATUS dcesrv_lsa_EnumPrivs(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
291 struct lsa_EnumPrivs *r)
293 struct dcesrv_handle *h;
294 struct lsa_policy_state *state;
295 uint32_t i;
296 enum sec_privilege priv;
297 const char *privname;
299 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
301 state = h->data;
303 i = *r->in.resume_handle;
305 while (((priv = sec_privilege_from_index(i)) != SEC_PRIV_INVALID) &&
306 r->out.privs->count < r->in.max_count) {
307 struct lsa_PrivEntry *e;
308 privname = sec_privilege_name(priv);
309 r->out.privs->privs = talloc_realloc(r->out.privs,
310 r->out.privs->privs,
311 struct lsa_PrivEntry,
312 r->out.privs->count+1);
313 if (r->out.privs->privs == NULL) {
314 return NT_STATUS_NO_MEMORY;
316 e = &r->out.privs->privs[r->out.privs->count];
317 e->luid.low = priv;
318 e->luid.high = 0;
319 e->name.string = privname;
320 r->out.privs->count++;
321 i++;
324 *r->out.resume_handle = i;
326 return NT_STATUS_OK;
331 lsa_QuerySecObj
333 static NTSTATUS dcesrv_lsa_QuerySecurity(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
334 struct lsa_QuerySecurity *r)
336 struct dcesrv_handle *h;
337 struct security_descriptor *sd;
338 NTSTATUS status;
339 struct dom_sid *sid;
341 DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
343 sid = &dce_call->conn->auth_state.session_info->security_token->sids[PRIMARY_USER_SID_INDEX];
345 if (h->wire_handle.handle_type == LSA_HANDLE_POLICY) {
346 status = dcesrv_build_lsa_sd(mem_ctx, &sd, sid, 0);
347 } else if (h->wire_handle.handle_type == LSA_HANDLE_ACCOUNT) {
348 status = dcesrv_build_lsa_sd(mem_ctx, &sd, sid,
349 LSA_ACCOUNT_ALL_ACCESS);
350 } else {
351 return NT_STATUS_INVALID_HANDLE;
353 NT_STATUS_NOT_OK_RETURN(status);
355 (*r->out.sdbuf) = talloc(mem_ctx, struct sec_desc_buf);
356 NT_STATUS_HAVE_NO_MEMORY(*r->out.sdbuf);
358 (*r->out.sdbuf)->sd = sd;
360 return NT_STATUS_OK;
365 lsa_SetSecObj
367 static NTSTATUS dcesrv_lsa_SetSecObj(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
368 struct lsa_SetSecObj *r)
370 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
375 lsa_ChangePassword
377 static NTSTATUS dcesrv_lsa_ChangePassword(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
378 struct lsa_ChangePassword *r)
380 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
384 dssetup_DsRoleGetPrimaryDomainInformation
386 This is not an LSA call, but is the only call left on the DSSETUP
387 pipe (after the pipe was truncated), and needs lsa_get_policy_state
389 static WERROR dcesrv_dssetup_DsRoleGetPrimaryDomainInformation(struct dcesrv_call_state *dce_call,
390 TALLOC_CTX *mem_ctx,
391 struct dssetup_DsRoleGetPrimaryDomainInformation *r)
393 union dssetup_DsRoleInfo *info;
395 info = talloc_zero(mem_ctx, union dssetup_DsRoleInfo);
396 W_ERROR_HAVE_NO_MEMORY(info);
398 switch (r->in.level) {
399 case DS_ROLE_BASIC_INFORMATION:
401 enum dssetup_DsRole role = DS_ROLE_STANDALONE_SERVER;
402 uint32_t flags = 0;
403 const char *domain = NULL;
404 const char *dns_domain = NULL;
405 const char *forest = NULL;
406 struct GUID domain_guid;
407 struct lsa_policy_state *state;
409 NTSTATUS status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx, &state);
410 if (!NT_STATUS_IS_OK(status)) {
411 return ntstatus_to_werror(status);
414 ZERO_STRUCT(domain_guid);
416 switch (lpcfg_server_role(dce_call->conn->dce_ctx->lp_ctx)) {
417 case ROLE_STANDALONE:
418 role = DS_ROLE_STANDALONE_SERVER;
419 break;
420 case ROLE_DOMAIN_MEMBER:
421 role = DS_ROLE_MEMBER_SERVER;
422 break;
423 case ROLE_DOMAIN_CONTROLLER:
424 if (samdb_is_pdc(state->sam_ldb)) {
425 role = DS_ROLE_PRIMARY_DC;
426 } else {
427 role = DS_ROLE_BACKUP_DC;
429 break;
432 switch (lpcfg_server_role(dce_call->conn->dce_ctx->lp_ctx)) {
433 case ROLE_STANDALONE:
434 domain = talloc_strdup(mem_ctx, lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx));
435 W_ERROR_HAVE_NO_MEMORY(domain);
436 break;
437 case ROLE_DOMAIN_MEMBER:
438 domain = talloc_strdup(mem_ctx, lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx));
439 W_ERROR_HAVE_NO_MEMORY(domain);
440 /* TODO: what is with dns_domain and forest and guid? */
441 break;
442 case ROLE_DOMAIN_CONTROLLER:
443 flags = DS_ROLE_PRIMARY_DS_RUNNING;
445 if (state->mixed_domain == 1) {
446 flags |= DS_ROLE_PRIMARY_DS_MIXED_MODE;
449 domain = state->domain_name;
450 dns_domain = state->domain_dns;
451 forest = state->forest_dns;
453 domain_guid = state->domain_guid;
454 flags |= DS_ROLE_PRIMARY_DOMAIN_GUID_PRESENT;
455 break;
458 info->basic.role = role;
459 info->basic.flags = flags;
460 info->basic.domain = domain;
461 info->basic.dns_domain = dns_domain;
462 info->basic.forest = forest;
463 info->basic.domain_guid = domain_guid;
465 r->out.info = info;
466 return WERR_OK;
468 case DS_ROLE_UPGRADE_STATUS:
470 info->upgrade.upgrading = DS_ROLE_NOT_UPGRADING;
471 info->upgrade.previous_role = DS_ROLE_PREVIOUS_UNKNOWN;
473 r->out.info = info;
474 return WERR_OK;
476 case DS_ROLE_OP_STATUS:
478 info->opstatus.status = DS_ROLE_OP_IDLE;
480 r->out.info = info;
481 return WERR_OK;
483 default:
484 return WERR_INVALID_PARAM;
489 fill in the AccountDomain info
491 static NTSTATUS dcesrv_lsa_info_AccountDomain(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
492 struct lsa_DomainInfo *info)
494 info->name.string = state->domain_name;
495 info->sid = state->domain_sid;
497 return NT_STATUS_OK;
501 fill in the DNS domain info
503 static NTSTATUS dcesrv_lsa_info_DNS(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
504 struct lsa_DnsDomainInfo *info)
506 info->name.string = state->domain_name;
507 info->sid = state->domain_sid;
508 info->dns_domain.string = state->domain_dns;
509 info->dns_forest.string = state->forest_dns;
510 info->domain_guid = state->domain_guid;
512 return NT_STATUS_OK;
516 lsa_QueryInfoPolicy2
518 static NTSTATUS dcesrv_lsa_QueryInfoPolicy2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
519 struct lsa_QueryInfoPolicy2 *r)
521 struct lsa_policy_state *state;
522 struct dcesrv_handle *h;
523 union lsa_PolicyInformation *info;
525 *r->out.info = NULL;
527 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
529 state = h->data;
531 info = talloc_zero(mem_ctx, union lsa_PolicyInformation);
532 if (!info) {
533 return NT_STATUS_NO_MEMORY;
535 *r->out.info = info;
537 switch (r->in.level) {
538 case LSA_POLICY_INFO_AUDIT_LOG:
539 /* we don't need to fill in any of this */
540 ZERO_STRUCT(info->audit_log);
541 return NT_STATUS_OK;
542 case LSA_POLICY_INFO_AUDIT_EVENTS:
543 /* we don't need to fill in any of this */
544 ZERO_STRUCT(info->audit_events);
545 return NT_STATUS_OK;
546 case LSA_POLICY_INFO_PD:
547 /* we don't need to fill in any of this */
548 ZERO_STRUCT(info->pd);
549 return NT_STATUS_OK;
551 case LSA_POLICY_INFO_DOMAIN:
552 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->domain);
553 case LSA_POLICY_INFO_ACCOUNT_DOMAIN:
554 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->account_domain);
555 case LSA_POLICY_INFO_L_ACCOUNT_DOMAIN:
556 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->l_account_domain);
558 case LSA_POLICY_INFO_ROLE:
559 info->role.role = LSA_ROLE_PRIMARY;
560 return NT_STATUS_OK;
562 case LSA_POLICY_INFO_DNS:
563 case LSA_POLICY_INFO_DNS_INT:
564 return dcesrv_lsa_info_DNS(state, mem_ctx, &info->dns);
566 case LSA_POLICY_INFO_REPLICA:
567 ZERO_STRUCT(info->replica);
568 return NT_STATUS_OK;
570 case LSA_POLICY_INFO_QUOTA:
571 ZERO_STRUCT(info->quota);
572 return NT_STATUS_OK;
574 case LSA_POLICY_INFO_MOD:
575 case LSA_POLICY_INFO_AUDIT_FULL_SET:
576 case LSA_POLICY_INFO_AUDIT_FULL_QUERY:
577 /* windows gives INVALID_PARAMETER */
578 *r->out.info = NULL;
579 return NT_STATUS_INVALID_PARAMETER;
582 *r->out.info = NULL;
583 return NT_STATUS_INVALID_INFO_CLASS;
587 lsa_QueryInfoPolicy
589 static NTSTATUS dcesrv_lsa_QueryInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
590 struct lsa_QueryInfoPolicy *r)
592 struct lsa_QueryInfoPolicy2 r2;
593 NTSTATUS status;
595 ZERO_STRUCT(r2);
597 r2.in.handle = r->in.handle;
598 r2.in.level = r->in.level;
599 r2.out.info = r->out.info;
601 status = dcesrv_lsa_QueryInfoPolicy2(dce_call, mem_ctx, &r2);
603 return status;
607 lsa_SetInfoPolicy
609 static NTSTATUS dcesrv_lsa_SetInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
610 struct lsa_SetInfoPolicy *r)
612 /* need to support this */
613 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
618 lsa_ClearAuditLog
620 static NTSTATUS dcesrv_lsa_ClearAuditLog(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
621 struct lsa_ClearAuditLog *r)
623 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
628 lsa_CreateAccount
630 This call does not seem to have any long-term effects, hence no database operations
632 we need to talk to the MS product group to find out what this account database means!
634 answer is that the lsa database is totally separate from the SAM and
635 ldap databases. We are going to need a separate ldb to store these
636 accounts. The SIDs on this account bear no relation to the SIDs in
639 static NTSTATUS dcesrv_lsa_CreateAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
640 struct lsa_CreateAccount *r)
642 struct lsa_account_state *astate;
644 struct lsa_policy_state *state;
645 struct dcesrv_handle *h, *ah;
647 ZERO_STRUCTP(r->out.acct_handle);
649 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
651 state = h->data;
653 astate = talloc(dce_call->conn, struct lsa_account_state);
654 if (astate == NULL) {
655 return NT_STATUS_NO_MEMORY;
658 astate->account_sid = dom_sid_dup(astate, r->in.sid);
659 if (astate->account_sid == NULL) {
660 talloc_free(astate);
661 return NT_STATUS_NO_MEMORY;
664 astate->policy = talloc_reference(astate, state);
665 astate->access_mask = r->in.access_mask;
667 ah = dcesrv_handle_new(dce_call->context, LSA_HANDLE_ACCOUNT);
668 if (!ah) {
669 talloc_free(astate);
670 return NT_STATUS_NO_MEMORY;
673 ah->data = talloc_steal(ah, astate);
675 *r->out.acct_handle = ah->wire_handle;
677 return NT_STATUS_OK;
682 lsa_EnumAccounts
684 static NTSTATUS dcesrv_lsa_EnumAccounts(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
685 struct lsa_EnumAccounts *r)
687 struct dcesrv_handle *h;
688 struct lsa_policy_state *state;
689 int ret;
690 struct ldb_message **res;
691 const char * const attrs[] = { "objectSid", NULL};
692 uint32_t count, i;
694 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
696 state = h->data;
698 /* NOTE: This call must only return accounts that have at least
699 one privilege set
701 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
702 "(&(objectSid=*)(privilege=*))");
703 if (ret < 0) {
704 return NT_STATUS_INTERNAL_DB_CORRUPTION;
707 if (*r->in.resume_handle >= ret) {
708 return NT_STATUS_NO_MORE_ENTRIES;
711 count = ret - *r->in.resume_handle;
712 if (count > r->in.num_entries) {
713 count = r->in.num_entries;
716 if (count == 0) {
717 return NT_STATUS_NO_MORE_ENTRIES;
720 r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, count);
721 if (r->out.sids->sids == NULL) {
722 return NT_STATUS_NO_MEMORY;
725 for (i=0;i<count;i++) {
726 r->out.sids->sids[i].sid =
727 samdb_result_dom_sid(r->out.sids->sids,
728 res[i + *r->in.resume_handle],
729 "objectSid");
730 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
733 r->out.sids->num_sids = count;
734 *r->out.resume_handle = count + *r->in.resume_handle;
736 return NT_STATUS_OK;
740 /* This decrypts and returns Trusted Domain Auth Information Internal data */
741 static NTSTATUS get_trustdom_auth_blob(struct dcesrv_call_state *dce_call,
742 TALLOC_CTX *mem_ctx, DATA_BLOB *auth_blob,
743 struct trustDomainPasswords *auth_struct)
745 DATA_BLOB session_key = data_blob(NULL, 0);
746 enum ndr_err_code ndr_err;
747 NTSTATUS nt_status;
749 nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
750 if (!NT_STATUS_IS_OK(nt_status)) {
751 return nt_status;
754 arcfour_crypt_blob(auth_blob->data, auth_blob->length, &session_key);
755 ndr_err = ndr_pull_struct_blob(auth_blob, mem_ctx,
756 auth_struct,
757 (ndr_pull_flags_fn_t)ndr_pull_trustDomainPasswords);
758 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
759 return NT_STATUS_INVALID_PARAMETER;
762 return NT_STATUS_OK;
765 static NTSTATUS get_trustauth_inout_blob(struct dcesrv_call_state *dce_call,
766 TALLOC_CTX *mem_ctx,
767 struct trustAuthInOutBlob *iopw,
768 DATA_BLOB *trustauth_blob)
770 enum ndr_err_code ndr_err;
772 ndr_err = ndr_push_struct_blob(trustauth_blob, mem_ctx,
773 iopw,
774 (ndr_push_flags_fn_t)ndr_push_trustAuthInOutBlob);
775 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
776 return NT_STATUS_INVALID_PARAMETER;
779 return NT_STATUS_OK;
782 static NTSTATUS add_trust_user(TALLOC_CTX *mem_ctx,
783 struct ldb_context *sam_ldb,
784 struct ldb_dn *base_dn,
785 const char *netbios_name,
786 struct trustAuthInOutBlob *in,
787 struct ldb_dn **user_dn)
789 struct ldb_message *msg;
790 struct ldb_dn *dn;
791 uint32_t i;
792 int ret;
794 dn = ldb_dn_copy(mem_ctx, base_dn);
795 if (!dn) {
796 return NT_STATUS_NO_MEMORY;
798 if (!ldb_dn_add_child_fmt(dn, "cn=%s$,cn=users", netbios_name)) {
799 return NT_STATUS_NO_MEMORY;
802 msg = ldb_msg_new(mem_ctx);
803 if (!msg) {
804 return NT_STATUS_NO_MEMORY;
806 msg->dn = dn;
808 ret = ldb_msg_add_string(msg, "objectClass", "user");
809 if (ret != LDB_SUCCESS) {
810 return NT_STATUS_NO_MEMORY;
813 ret = ldb_msg_add_fmt(msg, "samAccountName", "%s$", netbios_name);
814 if (ret != LDB_SUCCESS) {
815 return NT_STATUS_NO_MEMORY;
818 ret = samdb_msg_add_uint(sam_ldb, msg, msg, "userAccountControl",
819 UF_INTERDOMAIN_TRUST_ACCOUNT);
820 if (ret != LDB_SUCCESS) {
821 return NT_STATUS_NO_MEMORY;
824 for (i = 0; i < in->count; i++) {
825 const char *attribute;
826 struct ldb_val v;
827 switch (in->current.array[i].AuthType) {
828 case TRUST_AUTH_TYPE_NT4OWF:
829 attribute = "unicodePwd";
830 v.data = (uint8_t *)&in->current.array[i].AuthInfo.nt4owf.password;
831 v.length = 16;
832 break;
833 case TRUST_AUTH_TYPE_CLEAR:
834 attribute = "clearTextPassword";
835 v.data = in->current.array[i].AuthInfo.clear.password;
836 v.length = in->current.array[i].AuthInfo.clear.size;
837 break;
838 default:
839 continue;
842 ret = ldb_msg_add_value(msg, attribute, &v, NULL);
843 if (ret != LDB_SUCCESS) {
844 return NT_STATUS_NO_MEMORY;
848 /* create the trusted_domain user account */
849 ret = ldb_add(sam_ldb, msg);
850 if (ret != LDB_SUCCESS) {
851 DEBUG(0,("Failed to create user record %s: %s\n",
852 ldb_dn_get_linearized(msg->dn),
853 ldb_errstring(sam_ldb)));
855 switch (ret) {
856 case LDB_ERR_ENTRY_ALREADY_EXISTS:
857 return NT_STATUS_DOMAIN_EXISTS;
858 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
859 return NT_STATUS_ACCESS_DENIED;
860 default:
861 return NT_STATUS_INTERNAL_DB_CORRUPTION;
865 if (user_dn) {
866 *user_dn = dn;
868 return NT_STATUS_OK;
872 lsa_CreateTrustedDomainEx2
874 static NTSTATUS dcesrv_lsa_CreateTrustedDomain_base(struct dcesrv_call_state *dce_call,
875 TALLOC_CTX *mem_ctx,
876 struct lsa_CreateTrustedDomainEx2 *r,
877 int op,
878 struct lsa_TrustDomainInfoAuthInfo *unencrypted_auth_info)
880 struct dcesrv_handle *policy_handle;
881 struct lsa_policy_state *policy_state;
882 struct lsa_trusted_domain_state *trusted_domain_state;
883 struct dcesrv_handle *handle;
884 struct ldb_message **msgs, *msg;
885 const char *attrs[] = {
886 NULL
888 const char *netbios_name;
889 const char *dns_name;
890 const char *name;
891 DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
892 struct trustDomainPasswords auth_struct;
893 int ret;
894 NTSTATUS nt_status;
895 struct ldb_context *sam_ldb;
897 DCESRV_PULL_HANDLE(policy_handle, r->in.policy_handle, LSA_HANDLE_POLICY);
898 ZERO_STRUCTP(r->out.trustdom_handle);
900 policy_state = policy_handle->data;
901 sam_ldb = policy_state->sam_ldb;
903 netbios_name = r->in.info->netbios_name.string;
904 if (!netbios_name) {
905 return NT_STATUS_INVALID_PARAMETER;
908 dns_name = r->in.info->domain_name.string;
910 trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
911 if (!trusted_domain_state) {
912 return NT_STATUS_NO_MEMORY;
914 trusted_domain_state->policy = policy_state;
916 if (strcasecmp(netbios_name, "BUILTIN") == 0
917 || (dns_name && strcasecmp(dns_name, "BUILTIN") == 0)
918 || (dom_sid_in_domain(policy_state->builtin_sid, r->in.info->sid))) {
919 return NT_STATUS_INVALID_PARAMETER;
922 if (strcasecmp(netbios_name, policy_state->domain_name) == 0
923 || strcasecmp(netbios_name, policy_state->domain_dns) == 0
924 || (dns_name && strcasecmp(dns_name, policy_state->domain_dns) == 0)
925 || (dns_name && strcasecmp(dns_name, policy_state->domain_name) == 0)
926 || (dom_sid_equal(policy_state->domain_sid, r->in.info->sid))) {
927 return NT_STATUS_CURRENT_DOMAIN_NOT_ALLOWED;
930 /* While this is a REF pointer, some of the functions that wrap this don't provide this */
931 if (op == NDR_LSA_CREATETRUSTEDDOMAIN) {
932 /* No secrets are created at this time, for this function */
933 auth_struct.outgoing.count = 0;
934 auth_struct.incoming.count = 0;
935 } else if (op == NDR_LSA_CREATETRUSTEDDOMAINEX2) {
936 auth_blob = data_blob_const(r->in.auth_info_internal->auth_blob.data,
937 r->in.auth_info_internal->auth_blob.size);
938 nt_status = get_trustdom_auth_blob(dce_call, mem_ctx,
939 &auth_blob, &auth_struct);
940 if (!NT_STATUS_IS_OK(nt_status)) {
941 return nt_status;
943 } else if (op == NDR_LSA_CREATETRUSTEDDOMAINEX) {
945 if (unencrypted_auth_info->incoming_count > 1) {
946 return NT_STATUS_INVALID_PARAMETER;
949 /* more investigation required here, do not create secrets for
950 * now */
951 auth_struct.outgoing.count = 0;
952 auth_struct.incoming.count = 0;
953 } else {
954 return NT_STATUS_INVALID_PARAMETER;
957 if (auth_struct.incoming.count) {
958 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
959 &auth_struct.incoming,
960 &trustAuthIncoming);
961 if (!NT_STATUS_IS_OK(nt_status)) {
962 return nt_status;
964 } else {
965 trustAuthIncoming = data_blob(NULL, 0);
968 if (auth_struct.outgoing.count) {
969 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
970 &auth_struct.outgoing,
971 &trustAuthOutgoing);
972 if (!NT_STATUS_IS_OK(nt_status)) {
973 return nt_status;
975 } else {
976 trustAuthOutgoing = data_blob(NULL, 0);
979 ret = ldb_transaction_start(sam_ldb);
980 if (ret != LDB_SUCCESS) {
981 return NT_STATUS_INTERNAL_DB_CORRUPTION;
984 if (dns_name) {
985 char *dns_encoded = ldb_binary_encode_string(mem_ctx, dns_name);
986 char *netbios_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
987 /* search for the trusted_domain record */
988 ret = gendb_search(sam_ldb,
989 mem_ctx, policy_state->system_dn, &msgs, attrs,
990 "(&(|(flatname=%s)(cn=%s)(trustPartner=%s)(flatname=%s)(cn=%s)(trustPartner=%s))(objectclass=trustedDomain))",
991 dns_encoded, dns_encoded, dns_encoded, netbios_encoded, netbios_encoded, netbios_encoded);
992 if (ret > 0) {
993 ldb_transaction_cancel(sam_ldb);
994 return NT_STATUS_OBJECT_NAME_COLLISION;
996 } else {
997 char *netbios_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
998 /* search for the trusted_domain record */
999 ret = gendb_search(sam_ldb,
1000 mem_ctx, policy_state->system_dn, &msgs, attrs,
1001 "(&(|(flatname=%s)(cn=%s)(trustPartner=%s))(objectclass=trustedDomain))",
1002 netbios_encoded, netbios_encoded, netbios_encoded);
1003 if (ret > 0) {
1004 ldb_transaction_cancel(sam_ldb);
1005 return NT_STATUS_OBJECT_NAME_COLLISION;
1009 if (ret < 0 ) {
1010 ldb_transaction_cancel(sam_ldb);
1011 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1014 name = dns_name ? dns_name : netbios_name;
1016 msg = ldb_msg_new(mem_ctx);
1017 if (msg == NULL) {
1018 return NT_STATUS_NO_MEMORY;
1021 msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
1022 if ( ! ldb_dn_add_child_fmt(msg->dn, "cn=%s", name)) {
1023 ldb_transaction_cancel(sam_ldb);
1024 return NT_STATUS_NO_MEMORY;
1027 ldb_msg_add_string(msg, "flatname", netbios_name);
1029 if (r->in.info->sid) {
1030 ret = samdb_msg_add_dom_sid(sam_ldb, mem_ctx, msg, "securityIdentifier", r->in.info->sid);
1031 if (ret != LDB_SUCCESS) {
1032 ldb_transaction_cancel(sam_ldb);
1033 return NT_STATUS_INVALID_PARAMETER;
1037 ldb_msg_add_string(msg, "objectClass", "trustedDomain");
1039 samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustType", r->in.info->trust_type);
1041 samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustAttributes", r->in.info->trust_attributes);
1043 samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustDirection", r->in.info->trust_direction);
1045 if (dns_name) {
1046 ldb_msg_add_string(msg, "trustPartner", dns_name);
1049 if (trustAuthIncoming.data) {
1050 ret = ldb_msg_add_value(msg, "trustAuthIncoming", &trustAuthIncoming, NULL);
1051 if (ret != LDB_SUCCESS) {
1052 ldb_transaction_cancel(sam_ldb);
1053 return NT_STATUS_NO_MEMORY;
1056 if (trustAuthOutgoing.data) {
1057 ret = ldb_msg_add_value(msg, "trustAuthOutgoing", &trustAuthOutgoing, NULL);
1058 if (ret != LDB_SUCCESS) {
1059 ldb_transaction_cancel(sam_ldb);
1060 return NT_STATUS_NO_MEMORY;
1064 trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msg->dn);
1066 /* create the trusted_domain */
1067 ret = ldb_add(sam_ldb, msg);
1068 switch (ret) {
1069 case LDB_SUCCESS:
1070 break;
1071 case LDB_ERR_ENTRY_ALREADY_EXISTS:
1072 ldb_transaction_cancel(sam_ldb);
1073 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1074 ldb_dn_get_linearized(msg->dn),
1075 ldb_errstring(sam_ldb)));
1076 return NT_STATUS_DOMAIN_EXISTS;
1077 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1078 ldb_transaction_cancel(sam_ldb);
1079 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1080 ldb_dn_get_linearized(msg->dn),
1081 ldb_errstring(sam_ldb)));
1082 return NT_STATUS_ACCESS_DENIED;
1083 default:
1084 ldb_transaction_cancel(sam_ldb);
1085 DEBUG(0,("Failed to create user record %s: %s\n",
1086 ldb_dn_get_linearized(msg->dn),
1087 ldb_errstring(sam_ldb)));
1088 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1091 if (r->in.info->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
1092 struct ldb_dn *user_dn;
1093 /* Inbound trusts must also create a cn=users object to match */
1094 nt_status = add_trust_user(mem_ctx, sam_ldb,
1095 policy_state->domain_dn,
1096 netbios_name,
1097 &auth_struct.incoming,
1098 &user_dn);
1099 if (!NT_STATUS_IS_OK(nt_status)) {
1100 ldb_transaction_cancel(sam_ldb);
1101 return nt_status;
1104 /* save the trust user dn */
1105 trusted_domain_state->trusted_domain_user_dn
1106 = talloc_steal(trusted_domain_state, user_dn);
1109 ret = ldb_transaction_commit(sam_ldb);
1110 if (ret != LDB_SUCCESS) {
1111 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1114 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1115 if (!handle) {
1116 return NT_STATUS_NO_MEMORY;
1119 handle->data = talloc_steal(handle, trusted_domain_state);
1121 trusted_domain_state->access_mask = r->in.access_mask;
1122 trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
1124 *r->out.trustdom_handle = handle->wire_handle;
1126 return NT_STATUS_OK;
1130 lsa_CreateTrustedDomainEx2
1132 static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx2(struct dcesrv_call_state *dce_call,
1133 TALLOC_CTX *mem_ctx,
1134 struct lsa_CreateTrustedDomainEx2 *r)
1136 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, r, NDR_LSA_CREATETRUSTEDDOMAINEX2, NULL);
1139 lsa_CreateTrustedDomainEx
1141 static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx(struct dcesrv_call_state *dce_call,
1142 TALLOC_CTX *mem_ctx,
1143 struct lsa_CreateTrustedDomainEx *r)
1145 struct lsa_CreateTrustedDomainEx2 r2;
1147 r2.in.policy_handle = r->in.policy_handle;
1148 r2.in.info = r->in.info;
1149 r2.out.trustdom_handle = r->out.trustdom_handle;
1150 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAINEX, r->in.auth_info);
1154 lsa_CreateTrustedDomain
1156 static NTSTATUS dcesrv_lsa_CreateTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1157 struct lsa_CreateTrustedDomain *r)
1159 struct lsa_CreateTrustedDomainEx2 r2;
1161 r2.in.policy_handle = r->in.policy_handle;
1162 r2.in.info = talloc(mem_ctx, struct lsa_TrustDomainInfoInfoEx);
1163 if (!r2.in.info) {
1164 return NT_STATUS_NO_MEMORY;
1167 r2.in.info->domain_name.string = NULL;
1168 r2.in.info->netbios_name = r->in.info->name;
1169 r2.in.info->sid = r->in.info->sid;
1170 r2.in.info->trust_direction = LSA_TRUST_DIRECTION_OUTBOUND;
1171 r2.in.info->trust_type = LSA_TRUST_TYPE_DOWNLEVEL;
1172 r2.in.info->trust_attributes = 0;
1174 r2.in.access_mask = r->in.access_mask;
1175 r2.out.trustdom_handle = r->out.trustdom_handle;
1177 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAIN, NULL);
1182 lsa_OpenTrustedDomain
1184 static NTSTATUS dcesrv_lsa_OpenTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1185 struct lsa_OpenTrustedDomain *r)
1187 struct dcesrv_handle *policy_handle;
1189 struct lsa_policy_state *policy_state;
1190 struct lsa_trusted_domain_state *trusted_domain_state;
1191 struct dcesrv_handle *handle;
1192 struct ldb_message **msgs;
1193 const char *attrs[] = {
1194 "trustDirection",
1195 "flatname",
1196 NULL
1199 const char *sid_string;
1200 int ret;
1202 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1203 ZERO_STRUCTP(r->out.trustdom_handle);
1204 policy_state = policy_handle->data;
1206 trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
1207 if (!trusted_domain_state) {
1208 return NT_STATUS_NO_MEMORY;
1210 trusted_domain_state->policy = policy_state;
1212 sid_string = dom_sid_string(mem_ctx, r->in.sid);
1213 if (!sid_string) {
1214 return NT_STATUS_NO_MEMORY;
1217 /* search for the trusted_domain record */
1218 ret = gendb_search(trusted_domain_state->policy->sam_ldb,
1219 mem_ctx, policy_state->system_dn, &msgs, attrs,
1220 "(&(securityIdentifier=%s)(objectclass=trustedDomain))",
1221 sid_string);
1222 if (ret == 0) {
1223 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1226 if (ret != 1) {
1227 DEBUG(0,("Found %d records matching DN %s\n", ret,
1228 ldb_dn_get_linearized(policy_state->system_dn)));
1229 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1232 trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msgs[0]->dn);
1234 trusted_domain_state->trusted_domain_user_dn = NULL;
1236 if (ldb_msg_find_attr_as_int(msgs[0], "trustDirection", 0) & LSA_TRUST_DIRECTION_INBOUND) {
1237 const char *flatname = ldb_binary_encode_string(mem_ctx, ldb_msg_find_attr_as_string(msgs[0], "flatname", NULL));
1238 /* search for the trusted_domain record */
1239 ret = gendb_search(trusted_domain_state->policy->sam_ldb,
1240 mem_ctx, policy_state->domain_dn, &msgs, attrs,
1241 "(&(samaccountname=%s$)(objectclass=user)(userAccountControl:1.2.840.113556.1.4.803:=%u))",
1242 flatname, UF_INTERDOMAIN_TRUST_ACCOUNT);
1243 if (ret == 1) {
1244 trusted_domain_state->trusted_domain_user_dn = talloc_steal(trusted_domain_state, msgs[0]->dn);
1247 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1248 if (!handle) {
1249 return NT_STATUS_NO_MEMORY;
1252 handle->data = talloc_steal(handle, trusted_domain_state);
1254 trusted_domain_state->access_mask = r->in.access_mask;
1255 trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
1257 *r->out.trustdom_handle = handle->wire_handle;
1259 return NT_STATUS_OK;
1264 lsa_OpenTrustedDomainByName
1266 static NTSTATUS dcesrv_lsa_OpenTrustedDomainByName(struct dcesrv_call_state *dce_call,
1267 TALLOC_CTX *mem_ctx,
1268 struct lsa_OpenTrustedDomainByName *r)
1270 struct dcesrv_handle *policy_handle;
1272 struct lsa_policy_state *policy_state;
1273 struct lsa_trusted_domain_state *trusted_domain_state;
1274 struct dcesrv_handle *handle;
1275 struct ldb_message **msgs;
1276 const char *attrs[] = {
1277 NULL
1279 char *td_name;
1280 int ret;
1282 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1283 ZERO_STRUCTP(r->out.trustdom_handle);
1284 policy_state = policy_handle->data;
1286 if (!r->in.name.string) {
1287 return NT_STATUS_INVALID_PARAMETER;
1290 trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
1291 if (!trusted_domain_state) {
1292 return NT_STATUS_NO_MEMORY;
1294 trusted_domain_state->policy = policy_state;
1296 /* search for the trusted_domain record */
1297 td_name = ldb_binary_encode_string(mem_ctx, r->in.name.string);
1298 ret = gendb_search(trusted_domain_state->policy->sam_ldb,
1299 mem_ctx, policy_state->system_dn, &msgs, attrs,
1300 "(&(|(flatname=%s)(cn=%s)(trustPartner=%s))"
1301 "(objectclass=trustedDomain))",
1302 td_name, td_name, td_name);
1303 if (ret == 0) {
1304 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1307 if (ret != 1) {
1308 DEBUG(0,("Found %d records matching DN %s\n", ret,
1309 ldb_dn_get_linearized(policy_state->system_dn)));
1310 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1313 /* TODO: perform access checks */
1315 trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msgs[0]->dn);
1317 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1318 if (!handle) {
1319 return NT_STATUS_NO_MEMORY;
1322 handle->data = talloc_steal(handle, trusted_domain_state);
1324 trusted_domain_state->access_mask = r->in.access_mask;
1325 trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
1327 *r->out.trustdom_handle = handle->wire_handle;
1329 return NT_STATUS_OK;
1335 lsa_SetTrustedDomainInfo
1337 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1338 struct lsa_SetTrustedDomainInfo *r)
1340 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1345 /* parameters 4 to 6 are optional if the dn is a dn of a TDO object,
1346 * otherwise at least one must be provided */
1347 static NTSTATUS get_tdo(struct ldb_context *sam, TALLOC_CTX *mem_ctx,
1348 struct ldb_dn *basedn, const char *dns_domain,
1349 const char *netbios, struct dom_sid2 *sid,
1350 struct ldb_message ***msgs)
1352 const char *attrs[] = { "flatname", "trustPartner",
1353 "securityIdentifier", "trustDirection",
1354 "trustType", "trustAttributes",
1355 "trustPosixOffset",
1356 "msDs-supportedEncryptionTypes", NULL };
1357 char *dns = NULL;
1358 char *nbn = NULL;
1359 char *sidstr = NULL;
1360 char *filter;
1361 int ret;
1364 if (dns_domain || netbios || sid) {
1365 filter = talloc_strdup(mem_ctx,
1366 "(&(objectclass=trustedDomain)(|");
1367 } else {
1368 filter = talloc_strdup(mem_ctx,
1369 "(objectclass=trustedDomain)");
1371 if (!filter) {
1372 return NT_STATUS_NO_MEMORY;
1375 if (dns_domain) {
1376 dns = ldb_binary_encode_string(mem_ctx, dns_domain);
1377 if (!dns) {
1378 return NT_STATUS_NO_MEMORY;
1380 filter = talloc_asprintf_append(filter,
1381 "(trustPartner=%s)", dns);
1382 if (!filter) {
1383 return NT_STATUS_NO_MEMORY;
1386 if (netbios) {
1387 nbn = ldb_binary_encode_string(mem_ctx, netbios);
1388 if (!nbn) {
1389 return NT_STATUS_NO_MEMORY;
1391 filter = talloc_asprintf_append(filter,
1392 "(flatname=%s)", nbn);
1393 if (!filter) {
1394 return NT_STATUS_NO_MEMORY;
1397 if (sid) {
1398 sidstr = dom_sid_string(mem_ctx, sid);
1399 if (!sidstr) {
1400 return NT_STATUS_INVALID_PARAMETER;
1402 filter = talloc_asprintf_append(filter,
1403 "(securityIdentifier=%s)",
1404 sidstr);
1405 if (!filter) {
1406 return NT_STATUS_NO_MEMORY;
1409 if (dns_domain || netbios || sid) {
1410 filter = talloc_asprintf_append(filter, "))");
1411 if (!filter) {
1412 return NT_STATUS_NO_MEMORY;
1416 ret = gendb_search(sam, mem_ctx, basedn, msgs, attrs, "%s", filter);
1417 if (ret == 0) {
1418 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1421 if (ret != 1) {
1422 return NT_STATUS_OBJECT_NAME_COLLISION;
1425 return NT_STATUS_OK;
1428 static NTSTATUS update_uint32_t_value(TALLOC_CTX *mem_ctx,
1429 struct ldb_context *sam_ldb,
1430 struct ldb_message *orig,
1431 struct ldb_message *dest,
1432 const char *attribute,
1433 uint32_t value,
1434 uint32_t *orig_value)
1436 const struct ldb_val *orig_val;
1437 uint32_t orig_uint = 0;
1438 unsigned int flags = 0;
1439 int ret;
1441 orig_val = ldb_msg_find_ldb_val(orig, attribute);
1442 if (!orig_val || !orig_val->data) {
1443 /* add new attribute */
1444 flags = LDB_FLAG_MOD_ADD;
1446 } else {
1447 errno = 0;
1448 orig_uint = strtoul((const char *)orig_val->data, NULL, 0);
1449 if (errno != 0 || orig_uint != value) {
1450 /* replace also if can't get value */
1451 flags = LDB_FLAG_MOD_REPLACE;
1455 if (flags == 0) {
1456 /* stored value is identical, nothing to change */
1457 goto done;
1460 ret = ldb_msg_add_empty(dest, attribute, flags, NULL);
1461 if (ret != LDB_SUCCESS) {
1462 return NT_STATUS_NO_MEMORY;
1465 ret = samdb_msg_add_uint(sam_ldb, dest, dest, attribute, value);
1466 if (ret != LDB_SUCCESS) {
1467 return NT_STATUS_NO_MEMORY;
1470 done:
1471 if (orig_value) {
1472 *orig_value = orig_uint;
1474 return NT_STATUS_OK;
1477 static NTSTATUS update_trust_user(TALLOC_CTX *mem_ctx,
1478 struct ldb_context *sam_ldb,
1479 struct ldb_dn *base_dn,
1480 bool delete_user,
1481 const char *netbios_name,
1482 struct trustAuthInOutBlob *in)
1484 const char *attrs[] = { "userAccountControl", NULL };
1485 struct ldb_message **msgs;
1486 struct ldb_message *msg;
1487 uint32_t uac;
1488 uint32_t i;
1489 int ret;
1491 ret = gendb_search(sam_ldb, mem_ctx,
1492 base_dn, &msgs, attrs,
1493 "samAccountName=%s$", netbios_name);
1494 if (ret > 1) {
1495 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1498 if (ret == 0) {
1499 if (delete_user) {
1500 return NT_STATUS_OK;
1503 /* ok no existing user, add it from scratch */
1504 return add_trust_user(mem_ctx, sam_ldb, base_dn,
1505 netbios_name, in, NULL);
1508 /* check user is what we are looking for */
1509 uac = ldb_msg_find_attr_as_uint(msgs[0],
1510 "userAccountControl", 0);
1511 if (!(uac & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
1512 return NT_STATUS_OBJECT_NAME_COLLISION;
1515 if (delete_user) {
1516 ret = ldb_delete(sam_ldb, msgs[0]->dn);
1517 switch (ret) {
1518 case LDB_SUCCESS:
1519 return NT_STATUS_OK;
1520 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1521 return NT_STATUS_ACCESS_DENIED;
1522 default:
1523 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1527 /* entry exists, just modify secret if any */
1528 if (in == NULL || in->count == 0) {
1529 return NT_STATUS_OK;
1532 msg = ldb_msg_new(mem_ctx);
1533 if (!msg) {
1534 return NT_STATUS_NO_MEMORY;
1536 msg->dn = msgs[0]->dn;
1538 for (i = 0; i < in->count; i++) {
1539 const char *attribute;
1540 struct ldb_val v;
1541 switch (in->current.array[i].AuthType) {
1542 case TRUST_AUTH_TYPE_NT4OWF:
1543 attribute = "unicodePwd";
1544 v.data = (uint8_t *)&in->current.array[i].AuthInfo.nt4owf.password;
1545 v.length = 16;
1546 break;
1547 case TRUST_AUTH_TYPE_CLEAR:
1548 attribute = "clearTextPassword";
1549 v.data = in->current.array[i].AuthInfo.clear.password;
1550 v.length = in->current.array[i].AuthInfo.clear.size;
1551 break;
1552 default:
1553 continue;
1556 ret = ldb_msg_add_empty(msg, attribute,
1557 LDB_FLAG_MOD_REPLACE, NULL);
1558 if (ret != LDB_SUCCESS) {
1559 return NT_STATUS_NO_MEMORY;
1562 ret = ldb_msg_add_value(msg, attribute, &v, NULL);
1563 if (ret != LDB_SUCCESS) {
1564 return NT_STATUS_NO_MEMORY;
1568 /* create the trusted_domain user account */
1569 ret = ldb_modify(sam_ldb, msg);
1570 if (ret != LDB_SUCCESS) {
1571 DEBUG(0,("Failed to create user record %s: %s\n",
1572 ldb_dn_get_linearized(msg->dn),
1573 ldb_errstring(sam_ldb)));
1575 switch (ret) {
1576 case LDB_ERR_ENTRY_ALREADY_EXISTS:
1577 return NT_STATUS_DOMAIN_EXISTS;
1578 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1579 return NT_STATUS_ACCESS_DENIED;
1580 default:
1581 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1585 return NT_STATUS_OK;
1589 static NTSTATUS setInfoTrustedDomain_base(struct dcesrv_call_state *dce_call,
1590 struct dcesrv_handle *p_handle,
1591 TALLOC_CTX *mem_ctx,
1592 struct ldb_message *dom_msg,
1593 enum lsa_TrustDomInfoEnum level,
1594 union lsa_TrustedDomainInfo *info)
1596 struct lsa_policy_state *p_state = p_handle->data;
1597 uint32_t *posix_offset = NULL;
1598 struct lsa_TrustDomainInfoInfoEx *info_ex = NULL;
1599 struct lsa_TrustDomainInfoAuthInfo *auth_info = NULL;
1600 struct lsa_TrustDomainInfoAuthInfoInternal *auth_info_int = NULL;
1601 uint32_t *enc_types = NULL;
1602 DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
1603 struct trustDomainPasswords auth_struct;
1604 struct trustAuthInOutBlob *current_passwords = NULL;
1605 NTSTATUS nt_status;
1606 struct ldb_message **msgs;
1607 struct ldb_message *msg;
1608 bool add_outgoing = false;
1609 bool add_incoming = false;
1610 bool del_outgoing = false;
1611 bool del_incoming = false;
1612 bool in_transaction = false;
1613 int ret;
1614 bool am_rodc;
1616 switch (level) {
1617 case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
1618 posix_offset = &info->posix_offset.posix_offset;
1619 break;
1620 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
1621 info_ex = &info->info_ex;
1622 break;
1623 case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO:
1624 auth_info = &info->auth_info;
1625 break;
1626 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
1627 posix_offset = &info->full_info.posix_offset.posix_offset;
1628 info_ex = &info->full_info.info_ex;
1629 auth_info = &info->full_info.auth_info;
1630 break;
1631 case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO_INTERNAL:
1632 auth_info_int = &info->auth_info_internal;
1633 break;
1634 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_INTERNAL:
1635 posix_offset = &info->full_info_internal.posix_offset.posix_offset;
1636 info_ex = &info->full_info_internal.info_ex;
1637 auth_info_int = &info->full_info_internal.auth_info;
1638 break;
1639 case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
1640 enc_types = &info->enc_types.enc_types;
1641 break;
1642 default:
1643 return NT_STATUS_INVALID_PARAMETER;
1646 if (auth_info) {
1647 nt_status = auth_info_2_auth_blob(mem_ctx, auth_info,
1648 &trustAuthIncoming,
1649 &trustAuthOutgoing);
1650 if (!NT_STATUS_IS_OK(nt_status)) {
1651 return nt_status;
1653 if (trustAuthIncoming.data) {
1654 /* This does the decode of some of this twice, but it is easier that way */
1655 nt_status = auth_info_2_trustauth_inout(mem_ctx,
1656 auth_info->incoming_count,
1657 auth_info->incoming_current_auth_info,
1658 NULL,
1659 &current_passwords);
1660 if (!NT_STATUS_IS_OK(nt_status)) {
1661 return nt_status;
1666 /* decode auth_info_int if set */
1667 if (auth_info_int) {
1669 /* now decrypt blob */
1670 auth_blob = data_blob_const(auth_info_int->auth_blob.data,
1671 auth_info_int->auth_blob.size);
1673 nt_status = get_trustdom_auth_blob(dce_call, mem_ctx,
1674 &auth_blob, &auth_struct);
1675 if (!NT_STATUS_IS_OK(nt_status)) {
1676 return nt_status;
1680 if (info_ex) {
1681 /* verify data matches */
1682 if (info_ex->trust_attributes &
1683 LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
1684 /* TODO: check what behavior level we have */
1685 if (strcasecmp_m(p_state->domain_dns,
1686 p_state->forest_dns) != 0) {
1687 return NT_STATUS_INVALID_DOMAIN_STATE;
1691 ret = samdb_rodc(p_state->sam_ldb, &am_rodc);
1692 if (ret == LDB_SUCCESS && am_rodc) {
1693 return NT_STATUS_NO_SUCH_DOMAIN;
1696 /* verify only one object matches the dns/netbios/sid
1697 * triplet and that this is the one we already have */
1698 nt_status = get_tdo(p_state->sam_ldb, mem_ctx,
1699 p_state->system_dn,
1700 info_ex->domain_name.string,
1701 info_ex->netbios_name.string,
1702 info_ex->sid, &msgs);
1703 if (!NT_STATUS_IS_OK(nt_status)) {
1704 return nt_status;
1706 if (ldb_dn_compare(dom_msg->dn, msgs[0]->dn) != 0) {
1707 return NT_STATUS_OBJECT_NAME_COLLISION;
1709 talloc_free(msgs);
1712 /* TODO: should we fetch previous values from the existing entry
1713 * and append them ? */
1714 if (auth_info_int && auth_struct.incoming.count) {
1715 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1716 &auth_struct.incoming,
1717 &trustAuthIncoming);
1718 if (!NT_STATUS_IS_OK(nt_status)) {
1719 return nt_status;
1722 current_passwords = &auth_struct.incoming;
1724 } else {
1725 trustAuthIncoming = data_blob(NULL, 0);
1728 if (auth_info_int && auth_struct.outgoing.count) {
1729 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1730 &auth_struct.outgoing,
1731 &trustAuthOutgoing);
1732 if (!NT_STATUS_IS_OK(nt_status)) {
1733 return nt_status;
1735 } else {
1736 trustAuthOutgoing = data_blob(NULL, 0);
1739 msg = ldb_msg_new(mem_ctx);
1740 if (msg == NULL) {
1741 return NT_STATUS_NO_MEMORY;
1743 msg->dn = dom_msg->dn;
1745 if (posix_offset) {
1746 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1747 dom_msg, msg,
1748 "trustPosixOffset",
1749 *posix_offset, NULL);
1750 if (!NT_STATUS_IS_OK(nt_status)) {
1751 return nt_status;
1755 if (info_ex) {
1756 uint32_t origattrs;
1757 uint32_t origdir;
1758 int origtype;
1760 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1761 dom_msg, msg,
1762 "trustDirection",
1763 info_ex->trust_direction,
1764 &origdir);
1765 if (!NT_STATUS_IS_OK(nt_status)) {
1766 return nt_status;
1769 if (info_ex->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
1770 add_incoming = true;
1772 if (info_ex->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND) {
1773 add_outgoing = true;
1776 if ((origdir & LSA_TRUST_DIRECTION_INBOUND) &&
1777 !(info_ex->trust_direction & LSA_TRUST_DIRECTION_INBOUND)) {
1778 del_incoming = true;
1780 if ((origdir & LSA_TRUST_DIRECTION_OUTBOUND) &&
1781 !(info_ex->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND)) {
1782 del_outgoing = true;
1785 origtype = ldb_msg_find_attr_as_int(dom_msg, "trustType", -1);
1786 if (origtype == -1 || origtype != info_ex->trust_type) {
1787 DEBUG(1, ("Attempted to change trust type! "
1788 "Operation not handled\n"));
1789 return NT_STATUS_INVALID_PARAMETER;
1792 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1793 dom_msg, msg,
1794 "trustAttributes",
1795 info_ex->trust_attributes,
1796 &origattrs);
1797 if (!NT_STATUS_IS_OK(nt_status)) {
1798 return nt_status;
1800 /* TODO: check forestFunctionality from ldb opaque */
1801 /* TODO: check what is set makes sense */
1802 /* for now refuse changes */
1803 if (origattrs == -1 ||
1804 origattrs != info_ex->trust_attributes) {
1805 DEBUG(1, ("Attempted to change trust attributes! "
1806 "Operation not handled\n"));
1807 return NT_STATUS_INVALID_PARAMETER;
1811 if (enc_types) {
1812 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1813 dom_msg, msg,
1814 "msDS-SupportedEncryptionTypes",
1815 *enc_types, NULL);
1816 if (!NT_STATUS_IS_OK(nt_status)) {
1817 return nt_status;
1821 if (add_incoming && trustAuthIncoming.data) {
1822 ret = ldb_msg_add_empty(msg, "trustAuthIncoming",
1823 LDB_FLAG_MOD_REPLACE, NULL);
1824 if (ret != LDB_SUCCESS) {
1825 return NT_STATUS_NO_MEMORY;
1827 ret = ldb_msg_add_value(msg, "trustAuthIncoming",
1828 &trustAuthIncoming, NULL);
1829 if (ret != LDB_SUCCESS) {
1830 return NT_STATUS_NO_MEMORY;
1833 if (add_outgoing && trustAuthOutgoing.data) {
1834 ret = ldb_msg_add_empty(msg, "trustAuthOutgoing",
1835 LDB_FLAG_MOD_REPLACE, NULL);
1836 if (ret != LDB_SUCCESS) {
1837 return NT_STATUS_NO_MEMORY;
1839 ret = ldb_msg_add_value(msg, "trustAuthOutgoing",
1840 &trustAuthOutgoing, NULL);
1841 if (ret != LDB_SUCCESS) {
1842 return NT_STATUS_NO_MEMORY;
1846 /* start transaction */
1847 ret = ldb_transaction_start(p_state->sam_ldb);
1848 if (ret != LDB_SUCCESS) {
1849 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1851 in_transaction = true;
1853 if (msg->num_elements) {
1854 ret = ldb_modify(p_state->sam_ldb, msg);
1855 if (ret != LDB_SUCCESS) {
1856 DEBUG(1,("Failed to modify trusted domain record %s: %s\n",
1857 ldb_dn_get_linearized(msg->dn),
1858 ldb_errstring(p_state->sam_ldb)));
1859 nt_status = dsdb_ldb_err_to_ntstatus(ret);
1860 goto done;
1864 if (add_incoming || del_incoming) {
1865 const char *netbios_name;
1867 netbios_name = ldb_msg_find_attr_as_string(dom_msg,
1868 "flatname", NULL);
1869 if (!netbios_name) {
1870 nt_status = NT_STATUS_INVALID_DOMAIN_STATE;
1871 goto done;
1874 /* We use trustAuthIncoming.data to incidate that auth_struct.incoming is valid */
1875 nt_status = update_trust_user(mem_ctx,
1876 p_state->sam_ldb,
1877 p_state->domain_dn,
1878 del_incoming,
1879 netbios_name,
1880 current_passwords);
1881 if (!NT_STATUS_IS_OK(nt_status)) {
1882 goto done;
1886 /* ok, all fine, commit transaction and return */
1887 ret = ldb_transaction_commit(p_state->sam_ldb);
1888 if (ret != LDB_SUCCESS) {
1889 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1891 in_transaction = false;
1893 nt_status = NT_STATUS_OK;
1895 done:
1896 if (in_transaction) {
1897 ldb_transaction_cancel(p_state->sam_ldb);
1899 return nt_status;
1903 lsa_SetInfomrationTrustedDomain
1905 static NTSTATUS dcesrv_lsa_SetInformationTrustedDomain(
1906 struct dcesrv_call_state *dce_call,
1907 TALLOC_CTX *mem_ctx,
1908 struct lsa_SetInformationTrustedDomain *r)
1910 struct dcesrv_handle *h;
1911 struct lsa_trusted_domain_state *td_state;
1912 struct ldb_message **msgs;
1913 NTSTATUS nt_status;
1915 DCESRV_PULL_HANDLE(h, r->in.trustdom_handle,
1916 LSA_HANDLE_TRUSTED_DOMAIN);
1918 td_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
1920 /* get the trusted domain object */
1921 nt_status = get_tdo(td_state->policy->sam_ldb, mem_ctx,
1922 td_state->trusted_domain_dn,
1923 NULL, NULL, NULL, &msgs);
1924 if (!NT_STATUS_IS_OK(nt_status)) {
1925 if (NT_STATUS_EQUAL(nt_status,
1926 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1927 return nt_status;
1929 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1932 return setInfoTrustedDomain_base(dce_call, h, mem_ctx,
1933 msgs[0], r->in.level, r->in.info);
1938 lsa_DeleteTrustedDomain
1940 static NTSTATUS dcesrv_lsa_DeleteTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1941 struct lsa_DeleteTrustedDomain *r)
1943 NTSTATUS status;
1944 struct lsa_OpenTrustedDomain opn;
1945 struct lsa_DeleteObject del;
1946 struct dcesrv_handle *h;
1948 opn.in.handle = r->in.handle;
1949 opn.in.sid = r->in.dom_sid;
1950 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1951 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
1952 if (!opn.out.trustdom_handle) {
1953 return NT_STATUS_NO_MEMORY;
1955 status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
1956 if (!NT_STATUS_IS_OK(status)) {
1957 return status;
1960 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
1961 talloc_steal(mem_ctx, h);
1963 del.in.handle = opn.out.trustdom_handle;
1964 del.out.handle = opn.out.trustdom_handle;
1965 status = dcesrv_lsa_DeleteObject(dce_call, mem_ctx, &del);
1966 if (!NT_STATUS_IS_OK(status)) {
1967 return status;
1969 return NT_STATUS_OK;
1972 static NTSTATUS fill_trust_domain_ex(TALLOC_CTX *mem_ctx,
1973 struct ldb_message *msg,
1974 struct lsa_TrustDomainInfoInfoEx *info_ex)
1976 info_ex->domain_name.string
1977 = ldb_msg_find_attr_as_string(msg, "trustPartner", NULL);
1978 info_ex->netbios_name.string
1979 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
1980 info_ex->sid
1981 = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
1982 info_ex->trust_direction
1983 = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
1984 info_ex->trust_type
1985 = ldb_msg_find_attr_as_int(msg, "trustType", 0);
1986 info_ex->trust_attributes
1987 = ldb_msg_find_attr_as_int(msg, "trustAttributes", 0);
1988 return NT_STATUS_OK;
1992 lsa_QueryTrustedDomainInfo
1994 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1995 struct lsa_QueryTrustedDomainInfo *r)
1997 union lsa_TrustedDomainInfo *info = NULL;
1998 struct dcesrv_handle *h;
1999 struct lsa_trusted_domain_state *trusted_domain_state;
2000 struct ldb_message *msg;
2001 int ret;
2002 struct ldb_message **res;
2003 const char *attrs[] = {
2004 "flatname",
2005 "trustPartner",
2006 "securityIdentifier",
2007 "trustDirection",
2008 "trustType",
2009 "trustAttributes",
2010 "msDs-supportedEncryptionTypes",
2011 NULL
2014 DCESRV_PULL_HANDLE(h, r->in.trustdom_handle, LSA_HANDLE_TRUSTED_DOMAIN);
2016 trusted_domain_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
2018 /* pull all the user attributes */
2019 ret = gendb_search_dn(trusted_domain_state->policy->sam_ldb, mem_ctx,
2020 trusted_domain_state->trusted_domain_dn, &res, attrs);
2021 if (ret != 1) {
2022 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2024 msg = res[0];
2026 info = talloc_zero(mem_ctx, union lsa_TrustedDomainInfo);
2027 if (!info) {
2028 return NT_STATUS_NO_MEMORY;
2030 *r->out.info = info;
2032 switch (r->in.level) {
2033 case LSA_TRUSTED_DOMAIN_INFO_NAME:
2034 info->name.netbios_name.string
2035 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2036 break;
2037 case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
2038 info->posix_offset.posix_offset
2039 = ldb_msg_find_attr_as_uint(msg, "posixOffset", 0);
2040 break;
2041 #if 0 /* Win2k3 doesn't implement this */
2042 case LSA_TRUSTED_DOMAIN_INFO_BASIC:
2043 r->out.info->info_basic.netbios_name.string
2044 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2045 r->out.info->info_basic.sid
2046 = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
2047 break;
2048 #endif
2049 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
2050 return fill_trust_domain_ex(mem_ctx, msg, &info->info_ex);
2052 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
2053 ZERO_STRUCT(info->full_info);
2054 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info.info_ex);
2055 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_2_INTERNAL:
2056 ZERO_STRUCT(info->full_info2_internal);
2057 info->full_info2_internal.posix_offset.posix_offset
2058 = ldb_msg_find_attr_as_uint(msg, "posixOffset", 0);
2059 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info2_internal.info.info_ex);
2061 case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
2062 info->enc_types.enc_types
2063 = ldb_msg_find_attr_as_uint(msg, "msDs-supportedEncryptionTypes", KERB_ENCTYPE_RC4_HMAC_MD5);
2064 break;
2066 case LSA_TRUSTED_DOMAIN_INFO_CONTROLLERS:
2067 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX2_INTERNAL:
2068 /* oops, we don't want to return the info after all */
2069 talloc_free(info);
2070 *r->out.info = NULL;
2071 return NT_STATUS_INVALID_PARAMETER;
2072 default:
2073 /* oops, we don't want to return the info after all */
2074 talloc_free(info);
2075 *r->out.info = NULL;
2076 return NT_STATUS_INVALID_INFO_CLASS;
2079 return NT_STATUS_OK;
2084 lsa_QueryTrustedDomainInfoBySid
2086 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoBySid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2087 struct lsa_QueryTrustedDomainInfoBySid *r)
2089 NTSTATUS status;
2090 struct lsa_OpenTrustedDomain opn;
2091 struct lsa_QueryTrustedDomainInfo query;
2092 struct dcesrv_handle *h;
2094 opn.in.handle = r->in.handle;
2095 opn.in.sid = r->in.dom_sid;
2096 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2097 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2098 if (!opn.out.trustdom_handle) {
2099 return NT_STATUS_NO_MEMORY;
2101 status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
2102 if (!NT_STATUS_IS_OK(status)) {
2103 return status;
2106 /* Ensure this handle goes away at the end of this call */
2107 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2108 talloc_steal(mem_ctx, h);
2110 query.in.trustdom_handle = opn.out.trustdom_handle;
2111 query.in.level = r->in.level;
2112 query.out.info = r->out.info;
2113 status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2114 if (!NT_STATUS_IS_OK(status)) {
2115 return status;
2118 return NT_STATUS_OK;
2122 lsa_SetTrustedDomainInfoByName
2124 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2125 TALLOC_CTX *mem_ctx,
2126 struct lsa_SetTrustedDomainInfoByName *r)
2128 struct dcesrv_handle *policy_handle;
2129 struct lsa_policy_state *policy_state;
2130 struct ldb_message **msgs;
2131 NTSTATUS nt_status;
2133 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2134 policy_state = policy_handle->data;
2136 /* get the trusted domain object */
2137 nt_status = get_tdo(policy_state->sam_ldb, mem_ctx,
2138 policy_state->domain_dn,
2139 r->in.trusted_domain->string,
2140 r->in.trusted_domain->string,
2141 NULL, &msgs);
2142 if (!NT_STATUS_IS_OK(nt_status)) {
2143 if (NT_STATUS_EQUAL(nt_status,
2144 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2145 return nt_status;
2147 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2150 return setInfoTrustedDomain_base(dce_call, policy_handle, mem_ctx,
2151 msgs[0], r->in.level, r->in.info);
2155 lsa_QueryTrustedDomainInfoByName
2157 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2158 TALLOC_CTX *mem_ctx,
2159 struct lsa_QueryTrustedDomainInfoByName *r)
2161 NTSTATUS status;
2162 struct lsa_OpenTrustedDomainByName opn;
2163 struct lsa_QueryTrustedDomainInfo query;
2164 struct dcesrv_handle *h;
2166 opn.in.handle = r->in.handle;
2167 opn.in.name = *r->in.trusted_domain;
2168 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2169 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2170 if (!opn.out.trustdom_handle) {
2171 return NT_STATUS_NO_MEMORY;
2173 status = dcesrv_lsa_OpenTrustedDomainByName(dce_call, mem_ctx, &opn);
2174 if (!NT_STATUS_IS_OK(status)) {
2175 return status;
2178 /* Ensure this handle goes away at the end of this call */
2179 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2180 talloc_steal(mem_ctx, h);
2182 query.in.trustdom_handle = opn.out.trustdom_handle;
2183 query.in.level = r->in.level;
2184 query.out.info = r->out.info;
2185 status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2186 if (!NT_STATUS_IS_OK(status)) {
2187 return status;
2190 return NT_STATUS_OK;
2194 lsa_CloseTrustedDomainEx
2196 static NTSTATUS dcesrv_lsa_CloseTrustedDomainEx(struct dcesrv_call_state *dce_call,
2197 TALLOC_CTX *mem_ctx,
2198 struct lsa_CloseTrustedDomainEx *r)
2200 /* The result of a bad hair day from an IDL programmer? Not
2201 * implmented in Win2k3. You should always just lsa_Close
2202 * anyway. */
2203 return NT_STATUS_NOT_IMPLEMENTED;
2208 comparison function for sorting lsa_DomainInformation array
2210 static int compare_DomainInfo(struct lsa_DomainInfo *e1, struct lsa_DomainInfo *e2)
2212 return strcasecmp_m(e1->name.string, e2->name.string);
2216 lsa_EnumTrustDom
2218 static NTSTATUS dcesrv_lsa_EnumTrustDom(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2219 struct lsa_EnumTrustDom *r)
2221 struct dcesrv_handle *policy_handle;
2222 struct lsa_DomainInfo *entries;
2223 struct lsa_policy_state *policy_state;
2224 struct ldb_message **domains;
2225 const char *attrs[] = {
2226 "flatname",
2227 "securityIdentifier",
2228 NULL
2232 int count, i;
2234 *r->out.resume_handle = 0;
2236 r->out.domains->domains = NULL;
2237 r->out.domains->count = 0;
2239 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2241 policy_state = policy_handle->data;
2243 /* search for all users in this domain. This could possibly be cached and
2244 resumed based on resume_key */
2245 count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
2246 "objectclass=trustedDomain");
2247 if (count < 0) {
2248 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2251 /* convert to lsa_TrustInformation format */
2252 entries = talloc_array(mem_ctx, struct lsa_DomainInfo, count);
2253 if (!entries) {
2254 return NT_STATUS_NO_MEMORY;
2256 for (i=0;i<count;i++) {
2257 entries[i].sid = samdb_result_dom_sid(mem_ctx, domains[i], "securityIdentifier");
2258 entries[i].name.string = ldb_msg_find_attr_as_string(domains[i], "flatname", NULL);
2261 /* sort the results by name */
2262 TYPESAFE_QSORT(entries, count, compare_DomainInfo);
2264 if (*r->in.resume_handle >= count) {
2265 *r->out.resume_handle = -1;
2267 return NT_STATUS_NO_MORE_ENTRIES;
2270 /* return the rest, limit by max_size. Note that we
2271 use the w2k3 element size value of 60 */
2272 r->out.domains->count = count - *r->in.resume_handle;
2273 r->out.domains->count = MIN(r->out.domains->count,
2274 1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_MULTIPLIER));
2276 r->out.domains->domains = entries + *r->in.resume_handle;
2277 r->out.domains->count = r->out.domains->count;
2279 if (r->out.domains->count < count - *r->in.resume_handle) {
2280 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2281 return STATUS_MORE_ENTRIES;
2284 /* according to MS-LSAD 3.1.4.7.8 output resume handle MUST
2285 * always be larger than the previous input resume handle, in
2286 * particular when hitting the last query it is vital to set the
2287 * resume handle correctly to avoid infinite client loops, as
2288 * seen e.g. with Windows XP SP3 when resume handle is 0 and
2289 * status is NT_STATUS_OK - gd */
2291 *r->out.resume_handle = (uint32_t)-1;
2293 return NT_STATUS_OK;
2297 comparison function for sorting lsa_DomainInformation array
2299 static int compare_TrustDomainInfoInfoEx(struct lsa_TrustDomainInfoInfoEx *e1, struct lsa_TrustDomainInfoInfoEx *e2)
2301 return strcasecmp_m(e1->netbios_name.string, e2->netbios_name.string);
2305 lsa_EnumTrustedDomainsEx
2307 static NTSTATUS dcesrv_lsa_EnumTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2308 struct lsa_EnumTrustedDomainsEx *r)
2310 struct dcesrv_handle *policy_handle;
2311 struct lsa_TrustDomainInfoInfoEx *entries;
2312 struct lsa_policy_state *policy_state;
2313 struct ldb_message **domains;
2314 const char *attrs[] = {
2315 "flatname",
2316 "trustPartner",
2317 "securityIdentifier",
2318 "trustDirection",
2319 "trustType",
2320 "trustAttributes",
2321 NULL
2323 NTSTATUS nt_status;
2325 int count, i;
2327 *r->out.resume_handle = 0;
2329 r->out.domains->domains = NULL;
2330 r->out.domains->count = 0;
2332 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2334 policy_state = policy_handle->data;
2336 /* search for all users in this domain. This could possibly be cached and
2337 resumed based on resume_key */
2338 count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
2339 "objectclass=trustedDomain");
2340 if (count < 0) {
2341 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2344 /* convert to lsa_DomainInformation format */
2345 entries = talloc_array(mem_ctx, struct lsa_TrustDomainInfoInfoEx, count);
2346 if (!entries) {
2347 return NT_STATUS_NO_MEMORY;
2349 for (i=0;i<count;i++) {
2350 nt_status = fill_trust_domain_ex(mem_ctx, domains[i], &entries[i]);
2351 if (!NT_STATUS_IS_OK(nt_status)) {
2352 return nt_status;
2356 /* sort the results by name */
2357 TYPESAFE_QSORT(entries, count, compare_TrustDomainInfoInfoEx);
2359 if (*r->in.resume_handle >= count) {
2360 *r->out.resume_handle = -1;
2362 return NT_STATUS_NO_MORE_ENTRIES;
2365 /* return the rest, limit by max_size. Note that we
2366 use the w2k3 element size value of 60 */
2367 r->out.domains->count = count - *r->in.resume_handle;
2368 r->out.domains->count = MIN(r->out.domains->count,
2369 1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_EX_MULTIPLIER));
2371 r->out.domains->domains = entries + *r->in.resume_handle;
2372 r->out.domains->count = r->out.domains->count;
2374 if (r->out.domains->count < count - *r->in.resume_handle) {
2375 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2376 return STATUS_MORE_ENTRIES;
2379 return NT_STATUS_OK;
2384 lsa_OpenAccount
2386 static NTSTATUS dcesrv_lsa_OpenAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2387 struct lsa_OpenAccount *r)
2389 struct dcesrv_handle *h, *ah;
2390 struct lsa_policy_state *state;
2391 struct lsa_account_state *astate;
2393 ZERO_STRUCTP(r->out.acct_handle);
2395 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2397 state = h->data;
2399 astate = talloc(dce_call->conn, struct lsa_account_state);
2400 if (astate == NULL) {
2401 return NT_STATUS_NO_MEMORY;
2404 astate->account_sid = dom_sid_dup(astate, r->in.sid);
2405 if (astate->account_sid == NULL) {
2406 talloc_free(astate);
2407 return NT_STATUS_NO_MEMORY;
2410 astate->policy = talloc_reference(astate, state);
2411 astate->access_mask = r->in.access_mask;
2413 ah = dcesrv_handle_new(dce_call->context, LSA_HANDLE_ACCOUNT);
2414 if (!ah) {
2415 talloc_free(astate);
2416 return NT_STATUS_NO_MEMORY;
2419 ah->data = talloc_steal(ah, astate);
2421 *r->out.acct_handle = ah->wire_handle;
2423 return NT_STATUS_OK;
2428 lsa_EnumPrivsAccount
2430 static NTSTATUS dcesrv_lsa_EnumPrivsAccount(struct dcesrv_call_state *dce_call,
2431 TALLOC_CTX *mem_ctx,
2432 struct lsa_EnumPrivsAccount *r)
2434 struct dcesrv_handle *h;
2435 struct lsa_account_state *astate;
2436 int ret;
2437 unsigned int i, j;
2438 struct ldb_message **res;
2439 const char * const attrs[] = { "privilege", NULL};
2440 struct ldb_message_element *el;
2441 const char *sidstr;
2442 struct lsa_PrivilegeSet *privs;
2444 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2446 astate = h->data;
2448 privs = talloc(mem_ctx, struct lsa_PrivilegeSet);
2449 if (privs == NULL) {
2450 return NT_STATUS_NO_MEMORY;
2452 privs->count = 0;
2453 privs->unknown = 0;
2454 privs->set = NULL;
2456 *r->out.privs = privs;
2458 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
2459 if (sidstr == NULL) {
2460 return NT_STATUS_NO_MEMORY;
2463 ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs,
2464 "objectSid=%s", sidstr);
2465 if (ret < 0) {
2466 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2468 if (ret != 1) {
2469 return NT_STATUS_OK;
2472 el = ldb_msg_find_element(res[0], "privilege");
2473 if (el == NULL || el->num_values == 0) {
2474 return NT_STATUS_OK;
2477 privs->set = talloc_array(privs,
2478 struct lsa_LUIDAttribute, el->num_values);
2479 if (privs->set == NULL) {
2480 return NT_STATUS_NO_MEMORY;
2483 j = 0;
2484 for (i=0;i<el->num_values;i++) {
2485 int id = sec_privilege_id((const char *)el->values[i].data);
2486 if (id == SEC_PRIV_INVALID) {
2487 /* Perhaps an account right, not a privilege */
2488 continue;
2490 privs->set[j].attribute = 0;
2491 privs->set[j].luid.low = id;
2492 privs->set[j].luid.high = 0;
2493 j++;
2496 privs->count = j;
2498 return NT_STATUS_OK;
2502 lsa_EnumAccountRights
2504 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call,
2505 TALLOC_CTX *mem_ctx,
2506 struct lsa_EnumAccountRights *r)
2508 struct dcesrv_handle *h;
2509 struct lsa_policy_state *state;
2510 int ret;
2511 unsigned int i;
2512 struct ldb_message **res;
2513 const char * const attrs[] = { "privilege", NULL};
2514 const char *sidstr;
2515 struct ldb_message_element *el;
2517 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2519 state = h->data;
2521 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, r->in.sid);
2522 if (sidstr == NULL) {
2523 return NT_STATUS_NO_MEMORY;
2526 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
2527 "(&(objectSid=%s)(privilege=*))", sidstr);
2528 if (ret == 0) {
2529 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2531 if (ret != 1) {
2532 DEBUG(3, ("searching for account rights for SID: %s failed: %s",
2533 dom_sid_string(mem_ctx, r->in.sid),
2534 ldb_errstring(state->pdb)));
2535 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2538 el = ldb_msg_find_element(res[0], "privilege");
2539 if (el == NULL || el->num_values == 0) {
2540 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2543 r->out.rights->count = el->num_values;
2544 r->out.rights->names = talloc_array(r->out.rights,
2545 struct lsa_StringLarge, r->out.rights->count);
2546 if (r->out.rights->names == NULL) {
2547 return NT_STATUS_NO_MEMORY;
2550 for (i=0;i<el->num_values;i++) {
2551 r->out.rights->names[i].string = (const char *)el->values[i].data;
2554 return NT_STATUS_OK;
2560 helper for lsa_AddAccountRights and lsa_RemoveAccountRights
2562 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
2563 TALLOC_CTX *mem_ctx,
2564 struct lsa_policy_state *state,
2565 int ldb_flag,
2566 struct dom_sid *sid,
2567 const struct lsa_RightSet *rights)
2569 const char *sidstr, *sidndrstr;
2570 struct ldb_message *msg;
2571 struct ldb_message_element *el;
2572 int ret;
2573 uint32_t i;
2574 struct lsa_EnumAccountRights r2;
2575 char *dnstr;
2577 if (security_session_user_level(dce_call->conn->auth_state.session_info, NULL) <
2578 SECURITY_ADMINISTRATOR) {
2579 DEBUG(0,("lsa_AddRemoveAccount refused for supplied security token\n"));
2580 return NT_STATUS_ACCESS_DENIED;
2583 msg = ldb_msg_new(mem_ctx);
2584 if (msg == NULL) {
2585 return NT_STATUS_NO_MEMORY;
2588 sidndrstr = ldap_encode_ndr_dom_sid(msg, sid);
2589 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sidndrstr, msg);
2591 sidstr = dom_sid_string(msg, sid);
2592 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sidstr, msg);
2594 dnstr = talloc_asprintf(msg, "sid=%s", sidstr);
2595 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(dnstr, msg);
2597 msg->dn = ldb_dn_new(msg, state->pdb, dnstr);
2598 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(msg->dn, msg);
2600 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2601 NTSTATUS status;
2603 r2.in.handle = &state->handle->wire_handle;
2604 r2.in.sid = sid;
2605 r2.out.rights = talloc(mem_ctx, struct lsa_RightSet);
2607 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
2608 if (!NT_STATUS_IS_OK(status)) {
2609 ZERO_STRUCTP(r2.out.rights);
2613 for (i=0;i<rights->count;i++) {
2614 if (sec_privilege_id(rights->names[i].string) == SEC_PRIV_INVALID) {
2615 if (sec_right_bit(rights->names[i].string) == 0) {
2616 talloc_free(msg);
2617 return NT_STATUS_NO_SUCH_PRIVILEGE;
2620 talloc_free(msg);
2621 return NT_STATUS_NO_SUCH_PRIVILEGE;
2624 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2625 uint32_t j;
2626 for (j=0;j<r2.out.rights->count;j++) {
2627 if (strcasecmp_m(r2.out.rights->names[j].string,
2628 rights->names[i].string) == 0) {
2629 break;
2632 if (j != r2.out.rights->count) continue;
2635 ret = ldb_msg_add_string(msg, "privilege", rights->names[i].string);
2636 if (ret != LDB_SUCCESS) {
2637 talloc_free(msg);
2638 return NT_STATUS_NO_MEMORY;
2642 el = ldb_msg_find_element(msg, "privilege");
2643 if (!el) {
2644 talloc_free(msg);
2645 return NT_STATUS_OK;
2648 el->flags = ldb_flag;
2650 ret = ldb_modify(state->pdb, msg);
2651 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
2652 if (samdb_msg_add_dom_sid(state->pdb, msg, msg, "objectSid", sid) != LDB_SUCCESS) {
2653 talloc_free(msg);
2654 return NT_STATUS_NO_MEMORY;
2656 ldb_msg_add_string(msg, "comment", "added via LSA");
2657 ret = ldb_add(state->pdb, msg);
2659 if (ret != LDB_SUCCESS) {
2660 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE && ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
2661 talloc_free(msg);
2662 return NT_STATUS_OK;
2664 DEBUG(3, ("Could not %s attributes from %s: %s",
2665 LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE ? "delete" : "add",
2666 ldb_dn_get_linearized(msg->dn), ldb_errstring(state->pdb)));
2667 talloc_free(msg);
2668 return NT_STATUS_UNEXPECTED_IO_ERROR;
2671 talloc_free(msg);
2672 return NT_STATUS_OK;
2676 lsa_AddPrivilegesToAccount
2678 static NTSTATUS dcesrv_lsa_AddPrivilegesToAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2679 struct lsa_AddPrivilegesToAccount *r)
2681 struct lsa_RightSet rights;
2682 struct dcesrv_handle *h;
2683 struct lsa_account_state *astate;
2684 uint32_t i;
2686 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2688 astate = h->data;
2690 rights.count = r->in.privs->count;
2691 rights.names = talloc_array(mem_ctx, struct lsa_StringLarge, rights.count);
2692 if (rights.names == NULL) {
2693 return NT_STATUS_NO_MEMORY;
2695 for (i=0;i<rights.count;i++) {
2696 int id = r->in.privs->set[i].luid.low;
2697 if (r->in.privs->set[i].luid.high) {
2698 return NT_STATUS_NO_SUCH_PRIVILEGE;
2700 rights.names[i].string = sec_privilege_name(id);
2701 if (rights.names[i].string == NULL) {
2702 return NT_STATUS_NO_SUCH_PRIVILEGE;
2706 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
2707 LDB_FLAG_MOD_ADD, astate->account_sid,
2708 &rights);
2713 lsa_RemovePrivilegesFromAccount
2715 static NTSTATUS dcesrv_lsa_RemovePrivilegesFromAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2716 struct lsa_RemovePrivilegesFromAccount *r)
2718 struct lsa_RightSet *rights;
2719 struct dcesrv_handle *h;
2720 struct lsa_account_state *astate;
2721 uint32_t i;
2723 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2725 astate = h->data;
2727 rights = talloc(mem_ctx, struct lsa_RightSet);
2729 if (r->in.remove_all == 1 &&
2730 r->in.privs == NULL) {
2731 struct lsa_EnumAccountRights r2;
2732 NTSTATUS status;
2734 r2.in.handle = &astate->policy->handle->wire_handle;
2735 r2.in.sid = astate->account_sid;
2736 r2.out.rights = rights;
2738 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
2739 if (!NT_STATUS_IS_OK(status)) {
2740 return status;
2743 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
2744 LDB_FLAG_MOD_DELETE, astate->account_sid,
2745 r2.out.rights);
2748 if (r->in.remove_all != 0) {
2749 return NT_STATUS_INVALID_PARAMETER;
2752 rights->count = r->in.privs->count;
2753 rights->names = talloc_array(mem_ctx, struct lsa_StringLarge, rights->count);
2754 if (rights->names == NULL) {
2755 return NT_STATUS_NO_MEMORY;
2757 for (i=0;i<rights->count;i++) {
2758 int id = r->in.privs->set[i].luid.low;
2759 if (r->in.privs->set[i].luid.high) {
2760 return NT_STATUS_NO_SUCH_PRIVILEGE;
2762 rights->names[i].string = sec_privilege_name(id);
2763 if (rights->names[i].string == NULL) {
2764 return NT_STATUS_NO_SUCH_PRIVILEGE;
2768 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
2769 LDB_FLAG_MOD_DELETE, astate->account_sid,
2770 rights);
2775 lsa_GetQuotasForAccount
2777 static NTSTATUS dcesrv_lsa_GetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2778 struct lsa_GetQuotasForAccount *r)
2780 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2785 lsa_SetQuotasForAccount
2787 static NTSTATUS dcesrv_lsa_SetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2788 struct lsa_SetQuotasForAccount *r)
2790 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2795 lsa_GetSystemAccessAccount
2797 static NTSTATUS dcesrv_lsa_GetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2798 struct lsa_GetSystemAccessAccount *r)
2800 struct dcesrv_handle *h;
2801 struct lsa_account_state *astate;
2802 int ret;
2803 unsigned int i;
2804 struct ldb_message **res;
2805 const char * const attrs[] = { "privilege", NULL};
2806 struct ldb_message_element *el;
2807 const char *sidstr;
2809 *(r->out.access_mask) = 0x00000000;
2811 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2813 astate = h->data;
2815 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
2816 if (sidstr == NULL) {
2817 return NT_STATUS_NO_MEMORY;
2820 ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs,
2821 "objectSid=%s", sidstr);
2822 if (ret < 0) {
2823 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2825 if (ret != 1) {
2826 return NT_STATUS_OK;
2829 el = ldb_msg_find_element(res[0], "privilege");
2830 if (el == NULL || el->num_values == 0) {
2831 return NT_STATUS_OK;
2834 for (i=0;i<el->num_values;i++) {
2835 uint32_t right_bit = sec_right_bit((const char *)el->values[i].data);
2836 if (right_bit == 0) {
2837 /* Perhaps an privilege, not a right */
2838 continue;
2840 *(r->out.access_mask) |= right_bit;
2843 return NT_STATUS_OK;
2848 lsa_SetSystemAccessAccount
2850 static NTSTATUS dcesrv_lsa_SetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2851 struct lsa_SetSystemAccessAccount *r)
2853 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2858 lsa_CreateSecret
2860 static NTSTATUS dcesrv_lsa_CreateSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2861 struct lsa_CreateSecret *r)
2863 struct dcesrv_handle *policy_handle;
2864 struct lsa_policy_state *policy_state;
2865 struct lsa_secret_state *secret_state;
2866 struct dcesrv_handle *handle;
2867 struct ldb_message **msgs, *msg;
2868 const char *attrs[] = {
2869 NULL
2872 const char *name;
2874 int ret;
2876 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2877 ZERO_STRUCTP(r->out.sec_handle);
2879 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
2881 case SECURITY_SYSTEM:
2882 case SECURITY_ADMINISTRATOR:
2883 break;
2884 default:
2885 /* Users and annonymous are not allowed create secrets */
2886 return NT_STATUS_ACCESS_DENIED;
2889 policy_state = policy_handle->data;
2891 if (!r->in.name.string) {
2892 return NT_STATUS_INVALID_PARAMETER;
2895 secret_state = talloc(mem_ctx, struct lsa_secret_state);
2896 NT_STATUS_HAVE_NO_MEMORY(secret_state);
2897 secret_state->policy = policy_state;
2899 msg = ldb_msg_new(mem_ctx);
2900 if (msg == NULL) {
2901 return NT_STATUS_NO_MEMORY;
2904 if (strncmp("G$", r->in.name.string, 2) == 0) {
2905 const char *name2;
2907 secret_state->global = true;
2909 name = &r->in.name.string[2];
2910 if (strlen(name) == 0) {
2911 return NT_STATUS_INVALID_PARAMETER;
2914 name2 = talloc_asprintf(mem_ctx, "%s Secret",
2915 ldb_binary_encode_string(mem_ctx, name));
2916 NT_STATUS_HAVE_NO_MEMORY(name2);
2918 /* We need to connect to the database as system, as this is one
2919 * of the rare RPC calls that must read the secrets (and this
2920 * is denied otherwise) */
2921 secret_state->sam_ldb = talloc_reference(secret_state,
2922 samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(dce_call->conn->dce_ctx->lp_ctx), 0));
2923 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
2925 /* search for the secret record */
2926 ret = gendb_search(secret_state->sam_ldb,
2927 mem_ctx, policy_state->system_dn, &msgs, attrs,
2928 "(&(cn=%s)(objectclass=secret))",
2929 name2);
2930 if (ret > 0) {
2931 return NT_STATUS_OBJECT_NAME_COLLISION;
2934 if (ret < 0) {
2935 DEBUG(0,("Failure searching for CN=%s: %s\n",
2936 name2, ldb_errstring(secret_state->sam_ldb)));
2937 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2940 msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
2941 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
2942 if (!ldb_dn_add_child_fmt(msg->dn, "cn=%s", name2)) {
2943 return NT_STATUS_NO_MEMORY;
2946 ret = ldb_msg_add_string(msg, "cn", name2);
2947 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
2948 } else {
2949 secret_state->global = false;
2951 name = r->in.name.string;
2952 if (strlen(name) == 0) {
2953 return NT_STATUS_INVALID_PARAMETER;
2956 secret_state->sam_ldb = talloc_reference(secret_state,
2957 secrets_db_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
2958 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
2960 /* search for the secret record */
2961 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
2962 ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
2963 &msgs, attrs,
2964 "(&(cn=%s)(objectclass=secret))",
2965 ldb_binary_encode_string(mem_ctx, name));
2966 if (ret > 0) {
2967 return NT_STATUS_OBJECT_NAME_COLLISION;
2970 if (ret < 0) {
2971 DEBUG(0,("Failure searching for CN=%s: %s\n",
2972 name, ldb_errstring(secret_state->sam_ldb)));
2973 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2976 msg->dn = ldb_dn_new_fmt(mem_ctx, secret_state->sam_ldb,
2977 "cn=%s,cn=LSA Secrets", name);
2978 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
2979 ret = ldb_msg_add_string(msg, "cn", name);
2980 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
2983 ret = ldb_msg_add_string(msg, "objectClass", "secret");
2984 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
2986 secret_state->secret_dn = talloc_reference(secret_state, msg->dn);
2987 NT_STATUS_HAVE_NO_MEMORY(secret_state->secret_dn);
2989 /* create the secret */
2990 ret = ldb_add(secret_state->sam_ldb, msg);
2991 if (ret != LDB_SUCCESS) {
2992 DEBUG(0,("Failed to create secret record %s: %s\n",
2993 ldb_dn_get_linearized(msg->dn),
2994 ldb_errstring(secret_state->sam_ldb)));
2995 return NT_STATUS_ACCESS_DENIED;
2998 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
2999 NT_STATUS_HAVE_NO_MEMORY(handle);
3001 handle->data = talloc_steal(handle, secret_state);
3003 secret_state->access_mask = r->in.access_mask;
3004 secret_state->policy = talloc_reference(secret_state, policy_state);
3005 NT_STATUS_HAVE_NO_MEMORY(secret_state->policy);
3007 *r->out.sec_handle = handle->wire_handle;
3009 return NT_STATUS_OK;
3014 lsa_OpenSecret
3016 static NTSTATUS dcesrv_lsa_OpenSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3017 struct lsa_OpenSecret *r)
3019 struct dcesrv_handle *policy_handle;
3021 struct lsa_policy_state *policy_state;
3022 struct lsa_secret_state *secret_state;
3023 struct dcesrv_handle *handle;
3024 struct ldb_message **msgs;
3025 const char *attrs[] = {
3026 NULL
3029 const char *name;
3031 int ret;
3033 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
3034 ZERO_STRUCTP(r->out.sec_handle);
3035 policy_state = policy_handle->data;
3037 if (!r->in.name.string) {
3038 return NT_STATUS_INVALID_PARAMETER;
3041 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3043 case SECURITY_SYSTEM:
3044 case SECURITY_ADMINISTRATOR:
3045 break;
3046 default:
3047 /* Users and annonymous are not allowed to access secrets */
3048 return NT_STATUS_ACCESS_DENIED;
3051 secret_state = talloc(mem_ctx, struct lsa_secret_state);
3052 if (!secret_state) {
3053 return NT_STATUS_NO_MEMORY;
3055 secret_state->policy = policy_state;
3057 if (strncmp("G$", r->in.name.string, 2) == 0) {
3058 name = &r->in.name.string[2];
3059 /* We need to connect to the database as system, as this is one of the rare RPC calls that must read the secrets (and this is denied otherwise) */
3060 secret_state->sam_ldb = talloc_reference(secret_state,
3061 samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(dce_call->conn->dce_ctx->lp_ctx), 0));
3062 secret_state->global = true;
3064 if (strlen(name) < 1) {
3065 return NT_STATUS_INVALID_PARAMETER;
3068 /* search for the secret record */
3069 ret = gendb_search(secret_state->sam_ldb,
3070 mem_ctx, policy_state->system_dn, &msgs, attrs,
3071 "(&(cn=%s Secret)(objectclass=secret))",
3072 ldb_binary_encode_string(mem_ctx, name));
3073 if (ret == 0) {
3074 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3077 if (ret != 1) {
3078 DEBUG(0,("Found %d records matching DN %s\n", ret,
3079 ldb_dn_get_linearized(policy_state->system_dn)));
3080 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3083 } else {
3084 secret_state->global = false;
3085 secret_state->sam_ldb = talloc_reference(secret_state,
3086 secrets_db_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
3088 name = r->in.name.string;
3089 if (strlen(name) < 1) {
3090 return NT_STATUS_INVALID_PARAMETER;
3093 /* search for the secret record */
3094 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
3095 ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
3096 &msgs, attrs,
3097 "(&(cn=%s)(objectclass=secret))",
3098 ldb_binary_encode_string(mem_ctx, name));
3099 if (ret == 0) {
3100 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3103 if (ret != 1) {
3104 DEBUG(0,("Found %d records matching CN=%s\n",
3105 ret, ldb_binary_encode_string(mem_ctx, name)));
3106 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3110 secret_state->secret_dn = talloc_reference(secret_state, msgs[0]->dn);
3112 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
3113 if (!handle) {
3114 return NT_STATUS_NO_MEMORY;
3117 handle->data = talloc_steal(handle, secret_state);
3119 secret_state->access_mask = r->in.access_mask;
3120 secret_state->policy = talloc_reference(secret_state, policy_state);
3122 *r->out.sec_handle = handle->wire_handle;
3124 return NT_STATUS_OK;
3129 lsa_SetSecret
3131 static NTSTATUS dcesrv_lsa_SetSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3132 struct lsa_SetSecret *r)
3135 struct dcesrv_handle *h;
3136 struct lsa_secret_state *secret_state;
3137 struct ldb_message *msg;
3138 DATA_BLOB session_key;
3139 DATA_BLOB crypt_secret, secret;
3140 struct ldb_val val;
3141 int ret;
3142 NTSTATUS status = NT_STATUS_OK;
3144 struct timeval now = timeval_current();
3145 NTTIME nt_now = timeval_to_nttime(&now);
3147 DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3149 secret_state = h->data;
3151 msg = ldb_msg_new(mem_ctx);
3152 if (msg == NULL) {
3153 return NT_STATUS_NO_MEMORY;
3156 msg->dn = talloc_reference(mem_ctx, secret_state->secret_dn);
3157 if (!msg->dn) {
3158 return NT_STATUS_NO_MEMORY;
3160 status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
3161 if (!NT_STATUS_IS_OK(status)) {
3162 return status;
3165 if (r->in.old_val) {
3166 /* Decrypt */
3167 crypt_secret.data = r->in.old_val->data;
3168 crypt_secret.length = r->in.old_val->size;
3170 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3171 if (!NT_STATUS_IS_OK(status)) {
3172 return status;
3175 val.data = secret.data;
3176 val.length = secret.length;
3178 /* set value */
3179 if (ldb_msg_add_value(msg, "priorValue", &val, NULL) != LDB_SUCCESS) {
3180 return NT_STATUS_NO_MEMORY;
3183 /* set old value mtime */
3184 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3185 mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3186 return NT_STATUS_NO_MEMORY;
3189 } else {
3190 /* If the old value is not set, then migrate the
3191 * current value to the old value */
3192 const struct ldb_val *old_val;
3193 NTTIME last_set_time;
3194 struct ldb_message **res;
3195 const char *attrs[] = {
3196 "currentValue",
3197 "lastSetTime",
3198 NULL
3201 /* search for the secret record */
3202 ret = gendb_search_dn(secret_state->sam_ldb,mem_ctx,
3203 secret_state->secret_dn, &res, attrs);
3204 if (ret == 0) {
3205 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3208 if (ret != 1) {
3209 DEBUG(0,("Found %d records matching dn=%s\n", ret,
3210 ldb_dn_get_linearized(secret_state->secret_dn)));
3211 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3214 old_val = ldb_msg_find_ldb_val(res[0], "currentValue");
3215 last_set_time = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
3217 if (old_val) {
3218 /* set old value */
3219 if (ldb_msg_add_value(msg, "priorValue",
3220 old_val, NULL) != LDB_SUCCESS) {
3221 return NT_STATUS_NO_MEMORY;
3223 } else {
3224 if (samdb_msg_add_delete(secret_state->sam_ldb,
3225 mem_ctx, msg, "priorValue") != LDB_SUCCESS) {
3226 return NT_STATUS_NO_MEMORY;
3231 /* set old value mtime */
3232 if (ldb_msg_find_ldb_val(res[0], "lastSetTime")) {
3233 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3234 mem_ctx, msg, "priorSetTime", last_set_time) != LDB_SUCCESS) {
3235 return NT_STATUS_NO_MEMORY;
3237 } else {
3238 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3239 mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3240 return NT_STATUS_NO_MEMORY;
3245 if (r->in.new_val) {
3246 /* Decrypt */
3247 crypt_secret.data = r->in.new_val->data;
3248 crypt_secret.length = r->in.new_val->size;
3250 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3251 if (!NT_STATUS_IS_OK(status)) {
3252 return status;
3255 val.data = secret.data;
3256 val.length = secret.length;
3258 /* set value */
3259 if (ldb_msg_add_value(msg, "currentValue", &val, NULL) != LDB_SUCCESS) {
3260 return NT_STATUS_NO_MEMORY;
3263 /* set new value mtime */
3264 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3265 mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3266 return NT_STATUS_NO_MEMORY;
3269 } else {
3270 /* NULL out the NEW value */
3271 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3272 mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3273 return NT_STATUS_NO_MEMORY;
3275 if (samdb_msg_add_delete(secret_state->sam_ldb,
3276 mem_ctx, msg, "currentValue") != LDB_SUCCESS) {
3277 return NT_STATUS_NO_MEMORY;
3281 /* modify the samdb record */
3282 ret = dsdb_replace(secret_state->sam_ldb, msg, 0);
3283 if (ret != LDB_SUCCESS) {
3284 return dsdb_ldb_err_to_ntstatus(ret);
3287 return NT_STATUS_OK;
3292 lsa_QuerySecret
3294 static NTSTATUS dcesrv_lsa_QuerySecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3295 struct lsa_QuerySecret *r)
3297 struct dcesrv_handle *h;
3298 struct lsa_secret_state *secret_state;
3299 struct ldb_message *msg;
3300 DATA_BLOB session_key;
3301 DATA_BLOB crypt_secret, secret;
3302 int ret;
3303 struct ldb_message **res;
3304 const char *attrs[] = {
3305 "currentValue",
3306 "priorValue",
3307 "lastSetTime",
3308 "priorSetTime",
3309 NULL
3312 NTSTATUS nt_status;
3314 DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3316 /* Ensure user is permitted to read this... */
3317 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3319 case SECURITY_SYSTEM:
3320 case SECURITY_ADMINISTRATOR:
3321 break;
3322 default:
3323 /* Users and annonymous are not allowed to read secrets */
3324 return NT_STATUS_ACCESS_DENIED;
3327 secret_state = h->data;
3329 /* pull all the user attributes */
3330 ret = gendb_search_dn(secret_state->sam_ldb, mem_ctx,
3331 secret_state->secret_dn, &res, attrs);
3332 if (ret != 1) {
3333 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3335 msg = res[0];
3337 nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
3338 if (!NT_STATUS_IS_OK(nt_status)) {
3339 return nt_status;
3342 if (r->in.old_val) {
3343 const struct ldb_val *prior_val;
3344 r->out.old_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3345 if (!r->out.old_val) {
3346 return NT_STATUS_NO_MEMORY;
3348 prior_val = ldb_msg_find_ldb_val(res[0], "priorValue");
3350 if (prior_val && prior_val->length) {
3351 secret.data = prior_val->data;
3352 secret.length = prior_val->length;
3354 /* Encrypt */
3355 crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3356 if (!crypt_secret.length) {
3357 return NT_STATUS_NO_MEMORY;
3359 r->out.old_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3360 if (!r->out.old_val->buf) {
3361 return NT_STATUS_NO_MEMORY;
3363 r->out.old_val->buf->size = crypt_secret.length;
3364 r->out.old_val->buf->length = crypt_secret.length;
3365 r->out.old_val->buf->data = crypt_secret.data;
3369 if (r->in.old_mtime) {
3370 r->out.old_mtime = talloc(mem_ctx, NTTIME);
3371 if (!r->out.old_mtime) {
3372 return NT_STATUS_NO_MEMORY;
3374 *r->out.old_mtime = ldb_msg_find_attr_as_uint64(res[0], "priorSetTime", 0);
3377 if (r->in.new_val) {
3378 const struct ldb_val *new_val;
3379 r->out.new_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3380 if (!r->out.new_val) {
3381 return NT_STATUS_NO_MEMORY;
3384 new_val = ldb_msg_find_ldb_val(res[0], "currentValue");
3386 if (new_val && new_val->length) {
3387 secret.data = new_val->data;
3388 secret.length = new_val->length;
3390 /* Encrypt */
3391 crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3392 if (!crypt_secret.length) {
3393 return NT_STATUS_NO_MEMORY;
3395 r->out.new_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3396 if (!r->out.new_val->buf) {
3397 return NT_STATUS_NO_MEMORY;
3399 r->out.new_val->buf->length = crypt_secret.length;
3400 r->out.new_val->buf->size = crypt_secret.length;
3401 r->out.new_val->buf->data = crypt_secret.data;
3405 if (r->in.new_mtime) {
3406 r->out.new_mtime = talloc(mem_ctx, NTTIME);
3407 if (!r->out.new_mtime) {
3408 return NT_STATUS_NO_MEMORY;
3410 *r->out.new_mtime = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
3413 return NT_STATUS_OK;
3418 lsa_LookupPrivValue
3420 static NTSTATUS dcesrv_lsa_LookupPrivValue(struct dcesrv_call_state *dce_call,
3421 TALLOC_CTX *mem_ctx,
3422 struct lsa_LookupPrivValue *r)
3424 struct dcesrv_handle *h;
3425 struct lsa_policy_state *state;
3426 int id;
3428 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3430 state = h->data;
3432 id = sec_privilege_id(r->in.name->string);
3433 if (id == SEC_PRIV_INVALID) {
3434 return NT_STATUS_NO_SUCH_PRIVILEGE;
3437 r->out.luid->low = id;
3438 r->out.luid->high = 0;
3440 return NT_STATUS_OK;
3445 lsa_LookupPrivName
3447 static NTSTATUS dcesrv_lsa_LookupPrivName(struct dcesrv_call_state *dce_call,
3448 TALLOC_CTX *mem_ctx,
3449 struct lsa_LookupPrivName *r)
3451 struct dcesrv_handle *h;
3452 struct lsa_policy_state *state;
3453 struct lsa_StringLarge *name;
3454 const char *privname;
3456 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3458 state = h->data;
3460 if (r->in.luid->high != 0) {
3461 return NT_STATUS_NO_SUCH_PRIVILEGE;
3464 privname = sec_privilege_name(r->in.luid->low);
3465 if (privname == NULL) {
3466 return NT_STATUS_NO_SUCH_PRIVILEGE;
3469 name = talloc(mem_ctx, struct lsa_StringLarge);
3470 if (name == NULL) {
3471 return NT_STATUS_NO_MEMORY;
3474 name->string = privname;
3476 *r->out.name = name;
3478 return NT_STATUS_OK;
3483 lsa_LookupPrivDisplayName
3485 static NTSTATUS dcesrv_lsa_LookupPrivDisplayName(struct dcesrv_call_state *dce_call,
3486 TALLOC_CTX *mem_ctx,
3487 struct lsa_LookupPrivDisplayName *r)
3489 struct dcesrv_handle *h;
3490 struct lsa_policy_state *state;
3491 struct lsa_StringLarge *disp_name = NULL;
3492 enum sec_privilege id;
3494 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3496 state = h->data;
3498 id = sec_privilege_id(r->in.name->string);
3499 if (id == SEC_PRIV_INVALID) {
3500 return NT_STATUS_NO_SUCH_PRIVILEGE;
3503 disp_name = talloc(mem_ctx, struct lsa_StringLarge);
3504 if (disp_name == NULL) {
3505 return NT_STATUS_NO_MEMORY;
3508 disp_name->string = sec_privilege_display_name(id, &r->in.language_id);
3509 if (disp_name->string == NULL) {
3510 return NT_STATUS_INTERNAL_ERROR;
3513 *r->out.disp_name = disp_name;
3514 *r->out.returned_language_id = 0;
3516 return NT_STATUS_OK;
3521 lsa_EnumAccountsWithUserRight
3523 static NTSTATUS dcesrv_lsa_EnumAccountsWithUserRight(struct dcesrv_call_state *dce_call,
3524 TALLOC_CTX *mem_ctx,
3525 struct lsa_EnumAccountsWithUserRight *r)
3527 struct dcesrv_handle *h;
3528 struct lsa_policy_state *state;
3529 int ret, i;
3530 struct ldb_message **res;
3531 const char * const attrs[] = { "objectSid", NULL};
3532 const char *privname;
3534 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3536 state = h->data;
3538 if (r->in.name == NULL) {
3539 return NT_STATUS_NO_SUCH_PRIVILEGE;
3542 privname = r->in.name->string;
3543 if (sec_privilege_id(privname) == SEC_PRIV_INVALID && sec_right_bit(privname) == 0) {
3544 return NT_STATUS_NO_SUCH_PRIVILEGE;
3547 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
3548 "privilege=%s", privname);
3549 if (ret < 0) {
3550 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3552 if (ret == 0) {
3553 return NT_STATUS_NO_MORE_ENTRIES;
3556 r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, ret);
3557 if (r->out.sids->sids == NULL) {
3558 return NT_STATUS_NO_MEMORY;
3560 for (i=0;i<ret;i++) {
3561 r->out.sids->sids[i].sid = samdb_result_dom_sid(r->out.sids->sids,
3562 res[i], "objectSid");
3563 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
3565 r->out.sids->num_sids = ret;
3567 return NT_STATUS_OK;
3572 lsa_AddAccountRights
3574 static NTSTATUS dcesrv_lsa_AddAccountRights(struct dcesrv_call_state *dce_call,
3575 TALLOC_CTX *mem_ctx,
3576 struct lsa_AddAccountRights *r)
3578 struct dcesrv_handle *h;
3579 struct lsa_policy_state *state;
3581 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3583 state = h->data;
3585 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3586 LDB_FLAG_MOD_ADD,
3587 r->in.sid, r->in.rights);
3592 lsa_RemoveAccountRights
3594 static NTSTATUS dcesrv_lsa_RemoveAccountRights(struct dcesrv_call_state *dce_call,
3595 TALLOC_CTX *mem_ctx,
3596 struct lsa_RemoveAccountRights *r)
3598 struct dcesrv_handle *h;
3599 struct lsa_policy_state *state;
3601 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3603 state = h->data;
3605 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3606 LDB_FLAG_MOD_DELETE,
3607 r->in.sid, r->in.rights);
3612 lsa_StorePrivateData
3614 static NTSTATUS dcesrv_lsa_StorePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3615 struct lsa_StorePrivateData *r)
3617 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3622 lsa_RetrievePrivateData
3624 static NTSTATUS dcesrv_lsa_RetrievePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3625 struct lsa_RetrievePrivateData *r)
3627 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3632 lsa_GetUserName
3634 static NTSTATUS dcesrv_lsa_GetUserName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3635 struct lsa_GetUserName *r)
3637 NTSTATUS status = NT_STATUS_OK;
3638 const char *account_name;
3639 const char *authority_name;
3640 struct lsa_String *_account_name;
3641 struct lsa_String *_authority_name = NULL;
3643 /* this is what w2k3 does */
3644 r->out.account_name = r->in.account_name;
3645 r->out.authority_name = r->in.authority_name;
3647 if (r->in.account_name
3648 && *r->in.account_name
3649 /* && *(*r->in.account_name)->string */
3651 return NT_STATUS_INVALID_PARAMETER;
3654 if (r->in.authority_name
3655 && *r->in.authority_name
3656 /* && *(*r->in.authority_name)->string */
3658 return NT_STATUS_INVALID_PARAMETER;
3661 account_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->info->account_name);
3662 authority_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->info->domain_name);
3664 _account_name = talloc(mem_ctx, struct lsa_String);
3665 NT_STATUS_HAVE_NO_MEMORY(_account_name);
3666 _account_name->string = account_name;
3668 if (r->in.authority_name) {
3669 _authority_name = talloc(mem_ctx, struct lsa_String);
3670 NT_STATUS_HAVE_NO_MEMORY(_authority_name);
3671 _authority_name->string = authority_name;
3674 *r->out.account_name = _account_name;
3675 if (r->out.authority_name) {
3676 *r->out.authority_name = _authority_name;
3679 return status;
3683 lsa_SetInfoPolicy2
3685 static NTSTATUS dcesrv_lsa_SetInfoPolicy2(struct dcesrv_call_state *dce_call,
3686 TALLOC_CTX *mem_ctx,
3687 struct lsa_SetInfoPolicy2 *r)
3689 /* need to support these */
3690 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3693 static void kdc_get_policy(struct loadparm_context *lp_ctx,
3694 struct smb_krb5_context *smb_krb5_context,
3695 struct lsa_DomainInfoKerberos *k)
3697 time_t svc_tkt_lifetime;
3698 time_t usr_tkt_lifetime;
3699 time_t renewal_lifetime;
3701 /* These should be set and stored via Group Policy, but until then, some defaults are in order */
3703 /* Our KDC always re-validates the client */
3704 k->authentication_options = LSA_POLICY_KERBEROS_VALIDATE_CLIENT;
3706 lpcfg_default_kdc_policy(lp_ctx, &svc_tkt_lifetime,
3707 &usr_tkt_lifetime, &renewal_lifetime);
3709 unix_to_nt_time(&k->service_tkt_lifetime, svc_tkt_lifetime);
3710 unix_to_nt_time(&k->user_tkt_lifetime, usr_tkt_lifetime);
3711 unix_to_nt_time(&k->user_tkt_renewaltime, renewal_lifetime);
3712 #ifdef SAMBA4_USES_HEIMDAL /* MIT lacks krb5_get_max_time_skew.
3713 However in the parent function we basically just did a full
3714 krb5_context init with the only purpose of getting a global
3715 config option (the max skew), it would probably make more sense
3716 to have a lp_ or ldb global option as the samba default */
3717 if (smb_krb5_context) {
3718 unix_to_nt_time(&k->clock_skew,
3719 krb5_get_max_time_skew(smb_krb5_context->krb5_context));
3721 #endif
3722 k->reserved = 0;
3725 lsa_QueryDomainInformationPolicy
3727 static NTSTATUS dcesrv_lsa_QueryDomainInformationPolicy(struct dcesrv_call_state *dce_call,
3728 TALLOC_CTX *mem_ctx,
3729 struct lsa_QueryDomainInformationPolicy *r)
3731 union lsa_DomainInformationPolicy *info;
3733 info = talloc_zero(r->out.info, union lsa_DomainInformationPolicy);
3734 if (!info) {
3735 return NT_STATUS_NO_MEMORY;
3738 switch (r->in.level) {
3739 case LSA_DOMAIN_INFO_POLICY_EFS:
3740 talloc_free(info);
3741 *r->out.info = NULL;
3742 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3743 case LSA_DOMAIN_INFO_POLICY_KERBEROS:
3745 struct lsa_DomainInfoKerberos *k = &info->kerberos_info;
3746 struct smb_krb5_context *smb_krb5_context;
3747 int ret = smb_krb5_init_context(mem_ctx,
3748 dce_call->event_ctx,
3749 dce_call->conn->dce_ctx->lp_ctx,
3750 &smb_krb5_context);
3751 if (ret != 0) {
3752 talloc_free(info);
3753 *r->out.info = NULL;
3754 return NT_STATUS_INTERNAL_ERROR;
3756 kdc_get_policy(dce_call->conn->dce_ctx->lp_ctx,
3757 smb_krb5_context,
3759 talloc_free(smb_krb5_context);
3760 *r->out.info = info;
3761 return NT_STATUS_OK;
3763 default:
3764 talloc_free(info);
3765 *r->out.info = NULL;
3766 return NT_STATUS_INVALID_INFO_CLASS;
3771 lsa_SetDomInfoPolicy
3773 static NTSTATUS dcesrv_lsa_SetDomainInformationPolicy(struct dcesrv_call_state *dce_call,
3774 TALLOC_CTX *mem_ctx,
3775 struct lsa_SetDomainInformationPolicy *r)
3777 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3781 lsa_TestCall
3783 static NTSTATUS dcesrv_lsa_TestCall(struct dcesrv_call_state *dce_call,
3784 TALLOC_CTX *mem_ctx,
3785 struct lsa_TestCall *r)
3787 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3791 lsa_CREDRWRITE
3793 static NTSTATUS dcesrv_lsa_CREDRWRITE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3794 struct lsa_CREDRWRITE *r)
3796 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3801 lsa_CREDRREAD
3803 static NTSTATUS dcesrv_lsa_CREDRREAD(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3804 struct lsa_CREDRREAD *r)
3806 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3811 lsa_CREDRENUMERATE
3813 static NTSTATUS dcesrv_lsa_CREDRENUMERATE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3814 struct lsa_CREDRENUMERATE *r)
3816 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3821 lsa_CREDRWRITEDOMAINCREDENTIALS
3823 static NTSTATUS dcesrv_lsa_CREDRWRITEDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3824 struct lsa_CREDRWRITEDOMAINCREDENTIALS *r)
3826 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3831 lsa_CREDRREADDOMAINCREDENTIALS
3833 static NTSTATUS dcesrv_lsa_CREDRREADDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3834 struct lsa_CREDRREADDOMAINCREDENTIALS *r)
3836 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3841 lsa_CREDRDELETE
3843 static NTSTATUS dcesrv_lsa_CREDRDELETE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3844 struct lsa_CREDRDELETE *r)
3846 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3851 lsa_CREDRGETTARGETINFO
3853 static NTSTATUS dcesrv_lsa_CREDRGETTARGETINFO(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3854 struct lsa_CREDRGETTARGETINFO *r)
3856 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3861 lsa_CREDRPROFILELOADED
3863 static NTSTATUS dcesrv_lsa_CREDRPROFILELOADED(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3864 struct lsa_CREDRPROFILELOADED *r)
3866 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3871 lsa_CREDRGETSESSIONTYPES
3873 static NTSTATUS dcesrv_lsa_CREDRGETSESSIONTYPES(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3874 struct lsa_CREDRGETSESSIONTYPES *r)
3876 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3881 lsa_LSARREGISTERAUDITEVENT
3883 static NTSTATUS dcesrv_lsa_LSARREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3884 struct lsa_LSARREGISTERAUDITEVENT *r)
3886 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3891 lsa_LSARGENAUDITEVENT
3893 static NTSTATUS dcesrv_lsa_LSARGENAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3894 struct lsa_LSARGENAUDITEVENT *r)
3896 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3901 lsa_LSARUNREGISTERAUDITEVENT
3903 static NTSTATUS dcesrv_lsa_LSARUNREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3904 struct lsa_LSARUNREGISTERAUDITEVENT *r)
3906 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3911 lsa_lsaRQueryForestTrustInformation
3913 static NTSTATUS dcesrv_lsa_lsaRQueryForestTrustInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3914 struct lsa_lsaRQueryForestTrustInformation *r)
3916 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3919 #define DNS_CMP_MATCH 0
3920 #define DNS_CMP_FIRST_IS_CHILD 1
3921 #define DNS_CMP_SECOND_IS_CHILD 2
3922 #define DNS_CMP_NO_MATCH 3
3924 /* this function assumes names are well formed DNS names.
3925 * it doesn't validate them */
3926 static int dns_cmp(const char *s1, size_t l1,
3927 const char *s2, size_t l2)
3929 const char *p1, *p2;
3930 size_t t1, t2;
3931 int cret;
3933 if (l1 == l2) {
3934 if (strcasecmp_m(s1, s2) == 0) {
3935 return DNS_CMP_MATCH;
3937 return DNS_CMP_NO_MATCH;
3940 if (l1 > l2) {
3941 p1 = s1;
3942 p2 = s2;
3943 t1 = l1;
3944 t2 = l2;
3945 cret = DNS_CMP_FIRST_IS_CHILD;
3946 } else {
3947 p1 = s2;
3948 p2 = s1;
3949 t1 = l2;
3950 t2 = l1;
3951 cret = DNS_CMP_SECOND_IS_CHILD;
3954 if (p1[t1 - t2 - 1] != '.') {
3955 return DNS_CMP_NO_MATCH;
3958 if (strcasecmp_m(&p1[t1 - t2], p2) == 0) {
3959 return cret;
3962 return DNS_CMP_NO_MATCH;
3965 /* decode all TDOs forest trust info blobs */
3966 static NTSTATUS get_ft_info(TALLOC_CTX *mem_ctx,
3967 struct ldb_message *msg,
3968 struct ForestTrustInfo *info)
3970 const struct ldb_val *ft_blob;
3971 enum ndr_err_code ndr_err;
3973 ft_blob = ldb_msg_find_ldb_val(msg, "msDS-TrustForestTrustInfo");
3974 if (!ft_blob || !ft_blob->data) {
3975 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3977 /* ldb_val is equivalent to DATA_BLOB */
3978 ndr_err = ndr_pull_struct_blob_all(ft_blob, mem_ctx, info,
3979 (ndr_pull_flags_fn_t)ndr_pull_ForestTrustInfo);
3980 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
3981 return NT_STATUS_INVALID_DOMAIN_STATE;
3984 return NT_STATUS_OK;
3987 static NTSTATUS own_ft_info(struct lsa_policy_state *ps,
3988 struct ForestTrustInfo *fti)
3990 struct ForestTrustDataDomainInfo *info;
3991 struct ForestTrustInfoRecord *rec;
3993 fti->version = 1;
3994 fti->count = 2;
3995 fti->records = talloc_array(fti,
3996 struct ForestTrustInfoRecordArmor, 2);
3997 if (!fti->records) {
3998 return NT_STATUS_NO_MEMORY;
4001 /* TLN info */
4002 rec = &fti->records[0].record;
4004 rec->flags = 0;
4005 rec->timestamp = 0;
4006 rec->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
4008 rec->data.name.string = talloc_strdup(fti, ps->forest_dns);
4009 if (!rec->data.name.string) {
4010 return NT_STATUS_NO_MEMORY;
4012 rec->data.name.size = strlen(rec->data.name.string);
4014 /* DOMAIN info */
4015 rec = &fti->records[1].record;
4017 rec->flags = 0;
4018 rec->timestamp = 0;
4019 rec->type = LSA_FOREST_TRUST_DOMAIN_INFO;
4021 info = &rec->data.info;
4023 info->sid = *ps->domain_sid;
4024 info->dns_name.string = talloc_strdup(fti, ps->domain_dns);
4025 if (!info->dns_name.string) {
4026 return NT_STATUS_NO_MEMORY;
4028 info->dns_name.size = strlen(info->dns_name.string);
4029 info->netbios_name.string = talloc_strdup(fti, ps->domain_name);
4030 if (!info->netbios_name.string) {
4031 return NT_STATUS_NO_MEMORY;
4033 info->netbios_name.size = strlen(info->netbios_name.string);
4035 return NT_STATUS_OK;
4038 static NTSTATUS make_ft_info(TALLOC_CTX *mem_ctx,
4039 struct lsa_ForestTrustInformation *lfti,
4040 struct ForestTrustInfo *fti)
4042 struct lsa_ForestTrustRecord *lrec;
4043 struct ForestTrustInfoRecord *rec;
4044 struct lsa_StringLarge *tln;
4045 struct lsa_ForestTrustDomainInfo *info;
4046 uint32_t i;
4048 fti->version = 1;
4049 fti->count = lfti->count;
4050 fti->records = talloc_array(mem_ctx,
4051 struct ForestTrustInfoRecordArmor,
4052 fti->count);
4053 if (!fti->records) {
4054 return NT_STATUS_NO_MEMORY;
4056 for (i = 0; i < fti->count; i++) {
4057 lrec = lfti->entries[i];
4058 rec = &fti->records[i].record;
4060 rec->flags = lrec->flags;
4061 rec->timestamp = lrec->time;
4062 rec->type = lrec->type;
4064 switch (lrec->type) {
4065 case LSA_FOREST_TRUST_TOP_LEVEL_NAME:
4066 case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
4067 tln = &lrec->forest_trust_data.top_level_name;
4068 rec->data.name.string =
4069 talloc_strdup(mem_ctx, tln->string);
4070 if (!rec->data.name.string) {
4071 return NT_STATUS_NO_MEMORY;
4073 rec->data.name.size = strlen(rec->data.name.string);
4074 break;
4075 case LSA_FOREST_TRUST_DOMAIN_INFO:
4076 info = &lrec->forest_trust_data.domain_info;
4077 rec->data.info.sid = *info->domain_sid;
4078 rec->data.info.dns_name.string =
4079 talloc_strdup(mem_ctx,
4080 info->dns_domain_name.string);
4081 if (!rec->data.info.dns_name.string) {
4082 return NT_STATUS_NO_MEMORY;
4084 rec->data.info.dns_name.size =
4085 strlen(rec->data.info.dns_name.string);
4086 rec->data.info.netbios_name.string =
4087 talloc_strdup(mem_ctx,
4088 info->netbios_domain_name.string);
4089 if (!rec->data.info.netbios_name.string) {
4090 return NT_STATUS_NO_MEMORY;
4092 rec->data.info.netbios_name.size =
4093 strlen(rec->data.info.netbios_name.string);
4094 break;
4095 default:
4096 return NT_STATUS_INVALID_DOMAIN_STATE;
4100 return NT_STATUS_OK;
4103 static NTSTATUS add_collision(struct lsa_ForestTrustCollisionInfo *c_info,
4104 uint32_t idx, uint32_t collision_type,
4105 uint32_t conflict_type, const char *tdo_name);
4107 static NTSTATUS check_ft_info(TALLOC_CTX *mem_ctx,
4108 const char *tdo_name,
4109 struct ForestTrustInfo *tdo_fti,
4110 struct ForestTrustInfo *new_fti,
4111 struct lsa_ForestTrustCollisionInfo *c_info)
4113 struct ForestTrustInfoRecord *nrec;
4114 struct ForestTrustInfoRecord *trec;
4115 const char *dns_name;
4116 const char *nb_name;
4117 struct dom_sid *sid;
4118 const char *tname;
4119 size_t dns_len;
4120 size_t nb_len;
4121 size_t tlen;
4122 NTSTATUS nt_status;
4123 uint32_t new_fti_idx;
4124 uint32_t i;
4125 /* use always TDO type, until we understand when Xref can be used */
4126 uint32_t collision_type = LSA_FOREST_TRUST_COLLISION_TDO;
4127 bool tln_conflict;
4128 bool sid_conflict;
4129 bool nb_conflict;
4130 bool exclusion;
4131 bool ex_rule;
4132 int ret;
4134 for (new_fti_idx = 0; new_fti_idx < new_fti->count; new_fti_idx++) {
4136 nrec = &new_fti->records[new_fti_idx].record;
4137 dns_name = NULL;
4138 tln_conflict = false;
4139 sid_conflict = false;
4140 nb_conflict = false;
4141 exclusion = false;
4143 switch (nrec->type) {
4144 case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
4145 /* exclusions do not conflict by definition */
4146 break;
4148 case FOREST_TRUST_TOP_LEVEL_NAME:
4149 dns_name = nrec->data.name.string;
4150 dns_len = nrec->data.name.size;
4151 break;
4153 case LSA_FOREST_TRUST_DOMAIN_INFO:
4154 dns_name = nrec->data.info.dns_name.string;
4155 dns_len = nrec->data.info.dns_name.size;
4156 nb_name = nrec->data.info.netbios_name.string;
4157 nb_len = nrec->data.info.netbios_name.size;
4158 sid = &nrec->data.info.sid;
4159 break;
4162 if (!dns_name) continue;
4164 /* check if this is already taken and not excluded */
4165 for (i = 0; i < tdo_fti->count; i++) {
4166 trec = &tdo_fti->records[i].record;
4168 switch (trec->type) {
4169 case FOREST_TRUST_TOP_LEVEL_NAME:
4170 ex_rule = false;
4171 tname = trec->data.name.string;
4172 tlen = trec->data.name.size;
4173 break;
4174 case FOREST_TRUST_TOP_LEVEL_NAME_EX:
4175 ex_rule = true;
4176 tname = trec->data.name.string;
4177 tlen = trec->data.name.size;
4178 break;
4179 case FOREST_TRUST_DOMAIN_INFO:
4180 ex_rule = false;
4181 tname = trec->data.info.dns_name.string;
4182 tlen = trec->data.info.dns_name.size;
4184 ret = dns_cmp(dns_name, dns_len, tname, tlen);
4185 switch (ret) {
4186 case DNS_CMP_MATCH:
4187 /* if it matches exclusion,
4188 * it doesn't conflict */
4189 if (ex_rule) {
4190 exclusion = true;
4191 break;
4193 /* fall through */
4194 case DNS_CMP_FIRST_IS_CHILD:
4195 case DNS_CMP_SECOND_IS_CHILD:
4196 tln_conflict = true;
4197 /* fall through */
4198 default:
4199 break;
4202 /* explicit exclusion, no dns name conflict here */
4203 if (exclusion) {
4204 tln_conflict = false;
4207 if (trec->type != FOREST_TRUST_DOMAIN_INFO) {
4208 continue;
4211 /* also test for domain info */
4212 if (!(trec->flags & LSA_SID_DISABLED_ADMIN) &&
4213 dom_sid_compare(&trec->data.info.sid, sid) == 0) {
4214 sid_conflict = true;
4216 if (!(trec->flags & LSA_NB_DISABLED_ADMIN) &&
4217 strcasecmp_m(trec->data.info.netbios_name.string,
4218 nb_name) == 0) {
4219 nb_conflict = true;
4223 if (tln_conflict) {
4224 nt_status = add_collision(c_info, new_fti_idx,
4225 collision_type,
4226 LSA_TLN_DISABLED_CONFLICT,
4227 tdo_name);
4229 if (sid_conflict) {
4230 nt_status = add_collision(c_info, new_fti_idx,
4231 collision_type,
4232 LSA_SID_DISABLED_CONFLICT,
4233 tdo_name);
4235 if (nb_conflict) {
4236 nt_status = add_collision(c_info, new_fti_idx,
4237 collision_type,
4238 LSA_NB_DISABLED_CONFLICT,
4239 tdo_name);
4243 return NT_STATUS_OK;
4246 static NTSTATUS add_collision(struct lsa_ForestTrustCollisionInfo *c_info,
4247 uint32_t idx, uint32_t collision_type,
4248 uint32_t conflict_type, const char *tdo_name)
4250 struct lsa_ForestTrustCollisionRecord **es;
4251 uint32_t i = c_info->count;
4253 es = talloc_realloc(c_info, c_info->entries,
4254 struct lsa_ForestTrustCollisionRecord *, i + 1);
4255 if (!es) {
4256 return NT_STATUS_NO_MEMORY;
4258 c_info->entries = es;
4259 c_info->count = i + 1;
4261 es[i] = talloc(es, struct lsa_ForestTrustCollisionRecord);
4262 if (!es[i]) {
4263 return NT_STATUS_NO_MEMORY;
4266 es[i]->index = idx;
4267 es[i]->type = collision_type;
4268 es[i]->flags.flags = conflict_type;
4269 es[i]->name.string = talloc_strdup(es[i], tdo_name);
4270 if (!es[i]->name.string) {
4271 return NT_STATUS_NO_MEMORY;
4273 es[i]->name.size = strlen(es[i]->name.string);
4275 return NT_STATUS_OK;
4279 lsa_lsaRSetForestTrustInformation
4281 static NTSTATUS dcesrv_lsa_lsaRSetForestTrustInformation(struct dcesrv_call_state *dce_call,
4282 TALLOC_CTX *mem_ctx,
4283 struct lsa_lsaRSetForestTrustInformation *r)
4285 struct dcesrv_handle *h;
4286 struct lsa_policy_state *p_state;
4287 const char *trust_attrs[] = { "trustPartner", "trustAttributes",
4288 "msDS-TrustForestTrustInfo", NULL };
4289 struct ldb_message **dom_res = NULL;
4290 struct ldb_dn *tdo_dn;
4291 struct ldb_message *msg;
4292 int num_res, i;
4293 const char *td_name;
4294 uint32_t trust_attributes;
4295 struct lsa_ForestTrustCollisionInfo *c_info;
4296 struct ForestTrustInfo *nfti;
4297 struct ForestTrustInfo *fti;
4298 DATA_BLOB ft_blob;
4299 enum ndr_err_code ndr_err;
4300 NTSTATUS nt_status;
4301 bool am_rodc;
4302 int ret;
4304 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
4306 p_state = h->data;
4308 if (strcmp(p_state->domain_dns, p_state->forest_dns)) {
4309 return NT_STATUS_INVALID_DOMAIN_STATE;
4312 /* abort if we are not a PDC */
4313 if (!samdb_is_pdc(p_state->sam_ldb)) {
4314 return NT_STATUS_INVALID_DOMAIN_ROLE;
4317 ret = samdb_rodc(p_state->sam_ldb, &am_rodc);
4318 if (ret == LDB_SUCCESS && am_rodc) {
4319 return NT_STATUS_NO_SUCH_DOMAIN;
4322 /* check caller has TRUSTED_SET_AUTH */
4324 /* fetch all trusted domain objects */
4325 num_res = gendb_search(p_state->sam_ldb, mem_ctx,
4326 p_state->system_dn,
4327 &dom_res, trust_attrs,
4328 "(objectclass=trustedDomain)");
4329 if (num_res == 0) {
4330 return NT_STATUS_NO_SUCH_DOMAIN;
4333 for (i = 0; i < num_res; i++) {
4334 td_name = ldb_msg_find_attr_as_string(dom_res[i],
4335 "trustPartner", NULL);
4336 if (!td_name) {
4337 return NT_STATUS_INVALID_DOMAIN_STATE;
4339 if (strcasecmp_m(td_name,
4340 r->in.trusted_domain_name->string) == 0) {
4341 break;
4344 if (i >= num_res) {
4345 return NT_STATUS_NO_SUCH_DOMAIN;
4348 tdo_dn = dom_res[i]->dn;
4350 trust_attributes = ldb_msg_find_attr_as_uint(dom_res[i],
4351 "trustAttributes", 0);
4352 if (!(trust_attributes & NETR_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
4353 return NT_STATUS_INVALID_PARAMETER;
4356 if (r->in.highest_record_type >= LSA_FOREST_TRUST_RECORD_TYPE_LAST) {
4357 return NT_STATUS_INVALID_PARAMETER;
4360 nfti = talloc(mem_ctx, struct ForestTrustInfo);
4361 if (!nfti) {
4362 return NT_STATUS_NO_MEMORY;
4365 nt_status = make_ft_info(nfti, r->in.forest_trust_info, nfti);
4366 if (!NT_STATUS_IS_OK(nt_status)) {
4367 return nt_status;
4370 c_info = talloc_zero(r->out.collision_info,
4371 struct lsa_ForestTrustCollisionInfo);
4372 if (!c_info) {
4373 return NT_STATUS_NO_MEMORY;
4376 /* first check own info, then other domains */
4377 fti = talloc(mem_ctx, struct ForestTrustInfo);
4378 if (!fti) {
4379 return NT_STATUS_NO_MEMORY;
4382 nt_status = own_ft_info(p_state, fti);
4383 if (!NT_STATUS_IS_OK(nt_status)) {
4384 return nt_status;
4387 nt_status = check_ft_info(c_info, p_state->domain_dns,
4388 fti, nfti, c_info);
4389 if (!NT_STATUS_IS_OK(nt_status)) {
4390 return nt_status;
4393 for (i = 0; i < num_res; i++) {
4394 fti = talloc(mem_ctx, struct ForestTrustInfo);
4395 if (!fti) {
4396 return NT_STATUS_NO_MEMORY;
4399 nt_status = get_ft_info(mem_ctx, dom_res[i], fti);
4400 if (!NT_STATUS_IS_OK(nt_status)) {
4401 if (NT_STATUS_EQUAL(nt_status,
4402 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4403 continue;
4405 return nt_status;
4408 td_name = ldb_msg_find_attr_as_string(dom_res[i],
4409 "trustPartner", NULL);
4410 if (!td_name) {
4411 return NT_STATUS_INVALID_DOMAIN_STATE;
4414 nt_status = check_ft_info(c_info, td_name, fti, nfti, c_info);
4415 if (!NT_STATUS_IS_OK(nt_status)) {
4416 return nt_status;
4420 *r->out.collision_info = c_info;
4422 if (r->in.check_only != 0) {
4423 return NT_STATUS_OK;
4426 /* not just a check, write info back */
4428 ndr_err = ndr_push_struct_blob(&ft_blob, mem_ctx, nfti,
4429 (ndr_push_flags_fn_t)ndr_push_ForestTrustInfo);
4430 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
4431 return NT_STATUS_INVALID_PARAMETER;
4434 msg = ldb_msg_new(mem_ctx);
4435 if (msg == NULL) {
4436 return NT_STATUS_NO_MEMORY;
4439 msg->dn = ldb_dn_copy(mem_ctx, tdo_dn);
4440 if (!msg->dn) {
4441 return NT_STATUS_NO_MEMORY;
4444 ret = ldb_msg_add_empty(msg, "msDS-TrustForestTrustInfo",
4445 LDB_FLAG_MOD_REPLACE, NULL);
4446 if (ret != LDB_SUCCESS) {
4447 return NT_STATUS_NO_MEMORY;
4449 ret = ldb_msg_add_value(msg, "msDS-TrustForestTrustInfo",
4450 &ft_blob, NULL);
4451 if (ret != LDB_SUCCESS) {
4452 return NT_STATUS_NO_MEMORY;
4455 ret = ldb_modify(p_state->sam_ldb, msg);
4456 if (ret != LDB_SUCCESS) {
4457 DEBUG(0, ("Failed to store Forest Trust Info: %s\n",
4458 ldb_errstring(p_state->sam_ldb)));
4460 switch (ret) {
4461 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
4462 return NT_STATUS_ACCESS_DENIED;
4463 default:
4464 return NT_STATUS_INTERNAL_DB_CORRUPTION;
4468 return NT_STATUS_OK;
4472 lsa_CREDRRENAME
4474 static NTSTATUS dcesrv_lsa_CREDRRENAME(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4475 struct lsa_CREDRRENAME *r)
4477 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4483 lsa_LSAROPENPOLICYSCE
4485 static NTSTATUS dcesrv_lsa_LSAROPENPOLICYSCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4486 struct lsa_LSAROPENPOLICYSCE *r)
4488 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4493 lsa_LSARADTREGISTERSECURITYEVENTSOURCE
4495 static NTSTATUS dcesrv_lsa_LSARADTREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4496 struct lsa_LSARADTREGISTERSECURITYEVENTSOURCE *r)
4498 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4503 lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE
4505 static NTSTATUS dcesrv_lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4506 struct lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE *r)
4508 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4513 lsa_LSARADTREPORTSECURITYEVENT
4515 static NTSTATUS dcesrv_lsa_LSARADTREPORTSECURITYEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4516 struct lsa_LSARADTREPORTSECURITYEVENT *r)
4518 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4522 /* include the generated boilerplate */
4523 #include "librpc/gen_ndr/ndr_lsa_s.c"
4527 /*****************************************
4528 NOTE! The remaining calls below were
4529 removed in w2k3, so the DCESRV_FAULT()
4530 replies are the correct implementation. Do
4531 not try and fill these in with anything else
4532 ******************************************/
4535 dssetup_DsRoleDnsNameToFlatName
4537 static WERROR dcesrv_dssetup_DsRoleDnsNameToFlatName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4538 struct dssetup_DsRoleDnsNameToFlatName *r)
4540 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4545 dssetup_DsRoleDcAsDc
4547 static WERROR dcesrv_dssetup_DsRoleDcAsDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4548 struct dssetup_DsRoleDcAsDc *r)
4550 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4555 dssetup_DsRoleDcAsReplica
4557 static WERROR dcesrv_dssetup_DsRoleDcAsReplica(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4558 struct dssetup_DsRoleDcAsReplica *r)
4560 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4565 dssetup_DsRoleDemoteDc
4567 static WERROR dcesrv_dssetup_DsRoleDemoteDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4568 struct dssetup_DsRoleDemoteDc *r)
4570 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4575 dssetup_DsRoleGetDcOperationProgress
4577 static WERROR dcesrv_dssetup_DsRoleGetDcOperationProgress(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4578 struct dssetup_DsRoleGetDcOperationProgress *r)
4580 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4585 dssetup_DsRoleGetDcOperationResults
4587 static WERROR dcesrv_dssetup_DsRoleGetDcOperationResults(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4588 struct dssetup_DsRoleGetDcOperationResults *r)
4590 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4595 dssetup_DsRoleCancel
4597 static WERROR dcesrv_dssetup_DsRoleCancel(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4598 struct dssetup_DsRoleCancel *r)
4600 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4605 dssetup_DsRoleServerSaveStateForUpgrade
4607 static WERROR dcesrv_dssetup_DsRoleServerSaveStateForUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4608 struct dssetup_DsRoleServerSaveStateForUpgrade *r)
4610 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4615 dssetup_DsRoleUpgradeDownlevelServer
4617 static WERROR dcesrv_dssetup_DsRoleUpgradeDownlevelServer(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4618 struct dssetup_DsRoleUpgradeDownlevelServer *r)
4620 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4625 dssetup_DsRoleAbortDownlevelServerUpgrade
4627 static WERROR dcesrv_dssetup_DsRoleAbortDownlevelServerUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4628 struct dssetup_DsRoleAbortDownlevelServerUpgrade *r)
4630 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4634 /* include the generated boilerplate */
4635 #include "librpc/gen_ndr/ndr_dssetup_s.c"
4637 NTSTATUS dcerpc_server_lsa_init(void)
4639 NTSTATUS ret;
4641 ret = dcerpc_server_dssetup_init();
4642 if (!NT_STATUS_IS_OK(ret)) {
4643 return ret;
4645 ret = dcerpc_server_lsarpc_init();
4646 if (!NT_STATUS_IS_OK(ret)) {
4647 return ret;
4649 return ret;