1 /* need access mask/acl implementation */
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 "kdc/kdc-policy.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;
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;
56 struct ldb_dn *secret_dn;
57 struct ldb_context *sam_ldb;
62 state associated with a lsa_OpenTrustedDomain() operation
64 struct lsa_trusted_domain_state {
65 struct lsa_policy_state *policy;
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,
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,
102 SEC_ACE_TYPE_ACCESS_ALLOWED,
103 SEC_GENERIC_EXECUTE | SEC_GENERIC_READ, 0,
105 SID_BUILTIN_ADMINISTRATORS,
106 SEC_ACE_TYPE_ACCESS_ALLOWED,
109 SID_BUILTIN_ACCOUNT_OPERATORS,
110 SEC_ACE_TYPE_ACCESS_ALLOWED,
113 domain_admins_sid_str,
114 SEC_ACE_TYPE_ACCESS_ALLOWED,
118 SEC_ACE_TYPE_ACCESS_ALLOWED,
122 talloc_free(tmp_ctx);
124 NT_STATUS_HAVE_NO_MEMORY(*sd);
130 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call,
132 struct lsa_EnumAccountRights *r);
134 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
136 struct lsa_policy_state *state,
139 const struct lsa_RightSet *rights);
144 static NTSTATUS dcesrv_lsa_Close(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
147 struct dcesrv_handle *h;
149 *r->out.handle = *r->in.handle;
151 DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
155 ZERO_STRUCTP(r->out.handle);
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;
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;
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:
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);
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);
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;
245 rights = talloc(mem_ctx, struct lsa_RightSet);
247 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
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
258 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
259 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
263 if (!NT_STATUS_IS_OK(status)) {
267 status = dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
268 LDB_FLAG_MOD_DELETE, astate->account_sid,
270 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
274 if (!NT_STATUS_IS_OK(status)) {
278 ZERO_STRUCTP(r->out.handle);
283 return NT_STATUS_INVALID_HANDLE;
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;
296 enum sec_privilege priv;
297 const char *privname;
299 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
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,
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];
319 e->name.string = privname;
320 r->out.privs->count++;
324 *r->out.resume_handle = i;
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;
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);
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;
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);
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,
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;
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;
420 case ROLE_DOMAIN_MEMBER:
421 role = DS_ROLE_MEMBER_SERVER;
423 case ROLE_DOMAIN_CONTROLLER:
424 if (samdb_is_pdc(state->sam_ldb)) {
425 role = DS_ROLE_PRIMARY_DC;
427 role = DS_ROLE_BACKUP_DC;
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);
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? */
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;
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;
468 case DS_ROLE_UPGRADE_STATUS:
470 info->upgrade.upgrading = DS_ROLE_NOT_UPGRADING;
471 info->upgrade.previous_role = DS_ROLE_PREVIOUS_UNKNOWN;
476 case DS_ROLE_OP_STATUS:
478 info->opstatus.status = DS_ROLE_OP_IDLE;
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;
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;
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;
527 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
531 info = talloc_zero(mem_ctx, union lsa_PolicyInformation);
533 return NT_STATUS_NO_MEMORY;
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);
542 case LSA_POLICY_INFO_AUDIT_EVENTS:
543 /* we don't need to fill in any of this */
544 ZERO_STRUCT(info->audit_events);
546 case LSA_POLICY_INFO_PD:
547 /* we don't need to fill in any of this */
548 ZERO_STRUCT(info->pd);
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;
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);
570 case LSA_POLICY_INFO_QUOTA:
571 ZERO_STRUCT(info->quota);
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 */
579 return NT_STATUS_INVALID_PARAMETER;
583 return NT_STATUS_INVALID_INFO_CLASS;
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;
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);
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);
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);
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);
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) {
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);
670 return NT_STATUS_NO_MEMORY;
673 ah->data = talloc_steal(ah, astate);
675 *r->out.acct_handle = ah->wire_handle;
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;
690 struct ldb_message **res;
691 const char * const attrs[] = { "objectSid", NULL};
694 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
698 /* NOTE: This call must only return accounts that have at least
701 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
702 "(&(objectSid=*)(privilege=*))");
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;
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],
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;
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;
749 nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
750 if (!NT_STATUS_IS_OK(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,
757 (ndr_pull_flags_fn_t)ndr_pull_trustDomainPasswords);
758 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
759 return NT_STATUS_INVALID_PARAMETER;
765 static NTSTATUS get_trustauth_inout_blob(struct dcesrv_call_state *dce_call,
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,
774 (ndr_push_flags_fn_t)ndr_push_trustAuthInOutBlob);
775 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
776 return NT_STATUS_INVALID_PARAMETER;
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;
794 dn = ldb_dn_copy(mem_ctx, base_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);
804 return NT_STATUS_NO_MEMORY;
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;
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;
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;
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)));
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;
861 return NT_STATUS_INTERNAL_DB_CORRUPTION;
872 lsa_CreateTrustedDomainEx2
874 static NTSTATUS dcesrv_lsa_CreateTrustedDomain_base(struct dcesrv_call_state *dce_call,
876 struct lsa_CreateTrustedDomainEx2 *r,
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[] = {
888 const char *netbios_name;
889 const char *dns_name;
891 DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
892 struct trustDomainPasswords auth_struct;
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;
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)) {
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
951 auth_struct.outgoing.count = 0;
952 auth_struct.incoming.count = 0;
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,
961 if (!NT_STATUS_IS_OK(nt_status)) {
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,
972 if (!NT_STATUS_IS_OK(nt_status)) {
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;
985 char *dns_encoded = ldb_binary_encode_string(mem_ctx, netbios_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);
993 ldb_transaction_cancel(sam_ldb);
994 return NT_STATUS_OBJECT_NAME_COLLISION;
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);
1004 ldb_transaction_cancel(sam_ldb);
1005 return NT_STATUS_OBJECT_NAME_COLLISION;
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);
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);
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);
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;
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,
1097 &auth_struct.incoming,
1099 if (!NT_STATUS_IS_OK(nt_status)) {
1100 ldb_transaction_cancel(sam_ldb);
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);
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);
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[] = {
1199 const char *sid_string;
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);
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))",
1223 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
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);
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);
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[] = {
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);
1304 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
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);
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",
1356 "msDs-supportedEncryptionTypes", NULL };
1359 char *sidstr = NULL;
1364 if (dns_domain || netbios || sid) {
1365 filter = talloc_strdup(mem_ctx,
1366 "(&(objectclass=trustedDomain)(|");
1368 filter = talloc_strdup(mem_ctx,
1369 "(objectclass=trustedDomain)");
1372 return NT_STATUS_NO_MEMORY;
1376 dns = ldb_binary_encode_string(mem_ctx, dns_domain);
1378 return NT_STATUS_NO_MEMORY;
1380 filter = talloc_asprintf_append(filter,
1381 "(trustPartner=%s)", dns);
1383 return NT_STATUS_NO_MEMORY;
1387 nbn = ldb_binary_encode_string(mem_ctx, netbios);
1389 return NT_STATUS_NO_MEMORY;
1391 filter = talloc_asprintf_append(filter,
1392 "(flatname=%s)", nbn);
1394 return NT_STATUS_NO_MEMORY;
1398 sidstr = dom_sid_string(mem_ctx, sid);
1400 return NT_STATUS_INVALID_PARAMETER;
1402 filter = talloc_asprintf_append(filter,
1403 "(securityIdentifier=%s)",
1406 return NT_STATUS_NO_MEMORY;
1409 if (dns_domain || netbios || sid) {
1410 filter = talloc_asprintf_append(filter, "))");
1412 return NT_STATUS_NO_MEMORY;
1416 ret = gendb_search(sam, mem_ctx, basedn, msgs, attrs, "%s", filter);
1418 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
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,
1434 uint32_t *orig_value)
1436 const struct ldb_val *orig_val;
1437 uint32_t orig_uint = 0;
1438 unsigned int flags = 0;
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;
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;
1456 /* stored value is identical, nothing to change */
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;
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,
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;
1491 ret = gendb_search(sam_ldb, mem_ctx,
1492 base_dn, &msgs, attrs,
1493 "samAccountName=%s$", netbios_name);
1495 return NT_STATUS_INTERNAL_DB_CORRUPTION;
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;
1516 ret = ldb_delete(sam_ldb, msgs[0]->dn);
1519 return NT_STATUS_OK;
1520 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1521 return NT_STATUS_ACCESS_DENIED;
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);
1534 return NT_STATUS_NO_MEMORY;
1536 msg->dn = msgs[0]->dn;
1538 for (i = 0; i < in->count; i++) {
1539 const char *attribute;
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;
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;
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)));
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;
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 AuthenticationInformationArray *current_passwords = NULL;
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;
1617 case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
1618 posix_offset = &info->posix_offset.posix_offset;
1620 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
1621 info_ex = &info->info_ex;
1623 case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO:
1624 auth_info = &info->auth_info;
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;
1631 case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO_INTERNAL:
1632 auth_info_int = &info->auth_info_internal;
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;
1639 case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
1640 enc_types = &info->enc_types.enc_types;
1643 return NT_STATUS_INVALID_PARAMETER;
1647 /* FIXME: not handled yet */
1648 return NT_STATUS_INVALID_PARAMETER;
1651 /* decode auth_info_int if set */
1652 if (auth_info_int) {
1654 /* now decrypt blob */
1655 auth_blob = data_blob_const(auth_info_int->auth_blob.data,
1656 auth_info_int->auth_blob.size);
1658 nt_status = get_trustdom_auth_blob(dce_call, mem_ctx,
1659 &auth_blob, &auth_struct);
1660 if (!NT_STATUS_IS_OK(nt_status)) {
1666 /* verify data matches */
1667 if (info_ex->trust_attributes &
1668 LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
1669 /* TODO: check what behavior level we have */
1670 if (strcasecmp_m(p_state->domain_dns,
1671 p_state->forest_dns) != 0) {
1672 return NT_STATUS_INVALID_DOMAIN_STATE;
1676 ret = samdb_rodc(p_state->sam_ldb, &am_rodc);
1677 if (ret == LDB_SUCCESS && am_rodc) {
1678 return NT_STATUS_NO_SUCH_DOMAIN;
1681 /* verify only one object matches the dns/netbios/sid
1682 * triplet and that this is the one we already have */
1683 nt_status = get_tdo(p_state->sam_ldb, mem_ctx,
1685 info_ex->domain_name.string,
1686 info_ex->netbios_name.string,
1687 info_ex->sid, &msgs);
1688 if (!NT_STATUS_IS_OK(nt_status)) {
1691 if (ldb_dn_compare(dom_msg->dn, msgs[0]->dn) != 0) {
1692 return NT_STATUS_OBJECT_NAME_COLLISION;
1697 /* TODO: should we fetch previous values from the existing entry
1698 * and append them ? */
1699 if (auth_info_int && auth_struct.incoming.count) {
1700 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1701 &auth_struct.incoming,
1702 &trustAuthIncoming);
1703 if (!NT_STATUS_IS_OK(nt_status)) {
1707 current_passwords = &auth_struct.incoming;
1710 trustAuthIncoming = data_blob(NULL, 0);
1713 if (auth_info_int && auth_struct.outgoing.count) {
1714 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1715 &auth_struct.outgoing,
1716 &trustAuthOutgoing);
1717 if (!NT_STATUS_IS_OK(nt_status)) {
1721 trustAuthOutgoing = data_blob(NULL, 0);
1724 msg = ldb_msg_new(mem_ctx);
1726 return NT_STATUS_NO_MEMORY;
1728 msg->dn = dom_msg->dn;
1731 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1734 *posix_offset, NULL);
1735 if (!NT_STATUS_IS_OK(nt_status)) {
1745 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1748 info_ex->trust_direction,
1750 if (!NT_STATUS_IS_OK(nt_status)) {
1754 if (info_ex->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
1755 add_incoming = true;
1757 if (info_ex->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND) {
1758 add_outgoing = true;
1761 if ((origdir & LSA_TRUST_DIRECTION_INBOUND) &&
1762 !(info_ex->trust_direction & LSA_TRUST_DIRECTION_INBOUND)) {
1763 del_incoming = true;
1765 if ((origdir & LSA_TRUST_DIRECTION_OUTBOUND) &&
1766 !(info_ex->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND)) {
1767 del_outgoing = true;
1770 origtype = ldb_msg_find_attr_as_int(dom_msg, "trustType", -1);
1771 if (origtype == -1 || origtype != info_ex->trust_type) {
1772 DEBUG(1, ("Attempted to change trust type! "
1773 "Operation not handled\n"));
1774 return NT_STATUS_INVALID_PARAMETER;
1777 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1780 info_ex->trust_attributes,
1782 if (!NT_STATUS_IS_OK(nt_status)) {
1785 /* TODO: check forestFunctionality from ldb opaque */
1786 /* TODO: check what is set makes sense */
1787 /* for now refuse changes */
1788 if (origattrs == -1 ||
1789 origattrs != info_ex->trust_attributes) {
1790 DEBUG(1, ("Attempted to change trust attributes! "
1791 "Operation not handled\n"));
1792 return NT_STATUS_INVALID_PARAMETER;
1797 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1799 "msDS-SupportedEncryptionTypes",
1801 if (!NT_STATUS_IS_OK(nt_status)) {
1806 if (add_incoming && trustAuthIncoming.data) {
1807 ret = ldb_msg_add_empty(msg, "trustAuthIncoming",
1808 LDB_FLAG_MOD_REPLACE, NULL);
1809 if (ret != LDB_SUCCESS) {
1810 return NT_STATUS_NO_MEMORY;
1812 ret = ldb_msg_add_value(msg, "trustAuthIncoming",
1813 &trustAuthIncoming, NULL);
1814 if (ret != LDB_SUCCESS) {
1815 return NT_STATUS_NO_MEMORY;
1818 if (add_outgoing && trustAuthOutgoing.data) {
1819 ret = ldb_msg_add_empty(msg, "trustAuthOutgoing",
1820 LDB_FLAG_MOD_REPLACE, NULL);
1821 if (ret != LDB_SUCCESS) {
1822 return NT_STATUS_NO_MEMORY;
1824 ret = ldb_msg_add_value(msg, "trustAuthOutgoing",
1825 &trustAuthOutgoing, NULL);
1826 if (ret != LDB_SUCCESS) {
1827 return NT_STATUS_NO_MEMORY;
1831 /* start transaction */
1832 ret = ldb_transaction_start(p_state->sam_ldb);
1833 if (ret != LDB_SUCCESS) {
1834 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1836 in_transaction = true;
1838 if (msg->num_elements) {
1839 ret = ldb_modify(p_state->sam_ldb, msg);
1840 if (ret != LDB_SUCCESS) {
1841 DEBUG(1,("Failed to modify trusted domain record %s: %s\n",
1842 ldb_dn_get_linearized(msg->dn),
1843 ldb_errstring(p_state->sam_ldb)));
1844 nt_status = dsdb_ldb_err_to_ntstatus(ret);
1849 if (add_incoming || del_incoming) {
1850 const char *netbios_name;
1852 netbios_name = ldb_msg_find_attr_as_string(dom_msg,
1854 if (!netbios_name) {
1855 nt_status = NT_STATUS_INVALID_DOMAIN_STATE;
1859 /* We use trustAuthIncoming.data to incidate that auth_struct.incoming is valid */
1860 nt_status = update_trust_user(mem_ctx,
1866 if (!NT_STATUS_IS_OK(nt_status)) {
1871 /* ok, all fine, commit transaction and return */
1872 ret = ldb_transaction_commit(p_state->sam_ldb);
1873 if (ret != LDB_SUCCESS) {
1874 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1876 in_transaction = false;
1878 nt_status = NT_STATUS_OK;
1881 if (in_transaction) {
1882 ldb_transaction_cancel(p_state->sam_ldb);
1888 lsa_SetInfomrationTrustedDomain
1890 static NTSTATUS dcesrv_lsa_SetInformationTrustedDomain(
1891 struct dcesrv_call_state *dce_call,
1892 TALLOC_CTX *mem_ctx,
1893 struct lsa_SetInformationTrustedDomain *r)
1895 struct dcesrv_handle *h;
1896 struct lsa_trusted_domain_state *td_state;
1897 struct ldb_message **msgs;
1900 DCESRV_PULL_HANDLE(h, r->in.trustdom_handle,
1901 LSA_HANDLE_TRUSTED_DOMAIN);
1903 td_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
1905 /* get the trusted domain object */
1906 nt_status = get_tdo(td_state->policy->sam_ldb, mem_ctx,
1907 td_state->trusted_domain_dn,
1908 NULL, NULL, NULL, &msgs);
1909 if (!NT_STATUS_IS_OK(nt_status)) {
1910 if (NT_STATUS_EQUAL(nt_status,
1911 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1914 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1917 return setInfoTrustedDomain_base(dce_call, h, mem_ctx,
1918 msgs[0], r->in.level, r->in.info);
1923 lsa_DeleteTrustedDomain
1925 static NTSTATUS dcesrv_lsa_DeleteTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1926 struct lsa_DeleteTrustedDomain *r)
1929 struct lsa_OpenTrustedDomain opn;
1930 struct lsa_DeleteObject del;
1931 struct dcesrv_handle *h;
1933 opn.in.handle = r->in.handle;
1934 opn.in.sid = r->in.dom_sid;
1935 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1936 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
1937 if (!opn.out.trustdom_handle) {
1938 return NT_STATUS_NO_MEMORY;
1940 status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
1941 if (!NT_STATUS_IS_OK(status)) {
1945 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
1946 talloc_steal(mem_ctx, h);
1948 del.in.handle = opn.out.trustdom_handle;
1949 del.out.handle = opn.out.trustdom_handle;
1950 status = dcesrv_lsa_DeleteObject(dce_call, mem_ctx, &del);
1951 if (!NT_STATUS_IS_OK(status)) {
1954 return NT_STATUS_OK;
1957 static NTSTATUS fill_trust_domain_ex(TALLOC_CTX *mem_ctx,
1958 struct ldb_message *msg,
1959 struct lsa_TrustDomainInfoInfoEx *info_ex)
1961 info_ex->domain_name.string
1962 = ldb_msg_find_attr_as_string(msg, "trustPartner", NULL);
1963 info_ex->netbios_name.string
1964 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
1966 = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
1967 info_ex->trust_direction
1968 = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
1970 = ldb_msg_find_attr_as_int(msg, "trustType", 0);
1971 info_ex->trust_attributes
1972 = ldb_msg_find_attr_as_int(msg, "trustAttributes", 0);
1973 return NT_STATUS_OK;
1977 lsa_QueryTrustedDomainInfo
1979 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1980 struct lsa_QueryTrustedDomainInfo *r)
1982 union lsa_TrustedDomainInfo *info = NULL;
1983 struct dcesrv_handle *h;
1984 struct lsa_trusted_domain_state *trusted_domain_state;
1985 struct ldb_message *msg;
1987 struct ldb_message **res;
1988 const char *attrs[] = {
1991 "securityIdentifier",
1995 "msDs-supportedEncryptionTypes",
1999 DCESRV_PULL_HANDLE(h, r->in.trustdom_handle, LSA_HANDLE_TRUSTED_DOMAIN);
2001 trusted_domain_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
2003 /* pull all the user attributes */
2004 ret = gendb_search_dn(trusted_domain_state->policy->sam_ldb, mem_ctx,
2005 trusted_domain_state->trusted_domain_dn, &res, attrs);
2007 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2011 info = talloc_zero(mem_ctx, union lsa_TrustedDomainInfo);
2013 return NT_STATUS_NO_MEMORY;
2015 *r->out.info = info;
2017 switch (r->in.level) {
2018 case LSA_TRUSTED_DOMAIN_INFO_NAME:
2019 info->name.netbios_name.string
2020 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2022 case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
2023 info->posix_offset.posix_offset
2024 = ldb_msg_find_attr_as_uint(msg, "posixOffset", 0);
2026 #if 0 /* Win2k3 doesn't implement this */
2027 case LSA_TRUSTED_DOMAIN_INFO_BASIC:
2028 r->out.info->info_basic.netbios_name.string
2029 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2030 r->out.info->info_basic.sid
2031 = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
2034 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
2035 return fill_trust_domain_ex(mem_ctx, msg, &info->info_ex);
2037 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
2038 ZERO_STRUCT(info->full_info);
2039 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info.info_ex);
2040 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_2_INTERNAL:
2041 ZERO_STRUCT(info->full_info2_internal);
2042 info->full_info2_internal.posix_offset.posix_offset
2043 = ldb_msg_find_attr_as_uint(msg, "posixOffset", 0);
2044 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info2_internal.info.info_ex);
2046 case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
2047 info->enc_types.enc_types
2048 = ldb_msg_find_attr_as_uint(msg, "msDs-supportedEncryptionTypes", KERB_ENCTYPE_RC4_HMAC_MD5);
2051 case LSA_TRUSTED_DOMAIN_INFO_CONTROLLERS:
2052 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX2_INTERNAL:
2053 /* oops, we don't want to return the info after all */
2055 *r->out.info = NULL;
2056 return NT_STATUS_INVALID_PARAMETER;
2058 /* oops, we don't want to return the info after all */
2060 *r->out.info = NULL;
2061 return NT_STATUS_INVALID_INFO_CLASS;
2064 return NT_STATUS_OK;
2069 lsa_QueryTrustedDomainInfoBySid
2071 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoBySid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2072 struct lsa_QueryTrustedDomainInfoBySid *r)
2075 struct lsa_OpenTrustedDomain opn;
2076 struct lsa_QueryTrustedDomainInfo query;
2077 struct dcesrv_handle *h;
2079 opn.in.handle = r->in.handle;
2080 opn.in.sid = r->in.dom_sid;
2081 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2082 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2083 if (!opn.out.trustdom_handle) {
2084 return NT_STATUS_NO_MEMORY;
2086 status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
2087 if (!NT_STATUS_IS_OK(status)) {
2091 /* Ensure this handle goes away at the end of this call */
2092 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2093 talloc_steal(mem_ctx, h);
2095 query.in.trustdom_handle = opn.out.trustdom_handle;
2096 query.in.level = r->in.level;
2097 query.out.info = r->out.info;
2098 status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2099 if (!NT_STATUS_IS_OK(status)) {
2103 return NT_STATUS_OK;
2107 lsa_SetTrustedDomainInfoByName
2109 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2110 TALLOC_CTX *mem_ctx,
2111 struct lsa_SetTrustedDomainInfoByName *r)
2113 struct dcesrv_handle *policy_handle;
2114 struct lsa_policy_state *policy_state;
2115 struct ldb_message **msgs;
2118 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2119 policy_state = policy_handle->data;
2121 /* get the trusted domain object */
2122 nt_status = get_tdo(policy_state->sam_ldb, mem_ctx,
2123 policy_state->domain_dn,
2124 r->in.trusted_domain->string,
2125 r->in.trusted_domain->string,
2127 if (!NT_STATUS_IS_OK(nt_status)) {
2128 if (NT_STATUS_EQUAL(nt_status,
2129 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2132 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2135 return setInfoTrustedDomain_base(dce_call, policy_handle, mem_ctx,
2136 msgs[0], r->in.level, r->in.info);
2140 lsa_QueryTrustedDomainInfoByName
2142 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2143 TALLOC_CTX *mem_ctx,
2144 struct lsa_QueryTrustedDomainInfoByName *r)
2147 struct lsa_OpenTrustedDomainByName opn;
2148 struct lsa_QueryTrustedDomainInfo query;
2149 struct dcesrv_handle *h;
2151 opn.in.handle = r->in.handle;
2152 opn.in.name = *r->in.trusted_domain;
2153 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2154 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2155 if (!opn.out.trustdom_handle) {
2156 return NT_STATUS_NO_MEMORY;
2158 status = dcesrv_lsa_OpenTrustedDomainByName(dce_call, mem_ctx, &opn);
2159 if (!NT_STATUS_IS_OK(status)) {
2163 /* Ensure this handle goes away at the end of this call */
2164 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2165 talloc_steal(mem_ctx, h);
2167 query.in.trustdom_handle = opn.out.trustdom_handle;
2168 query.in.level = r->in.level;
2169 query.out.info = r->out.info;
2170 status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2171 if (!NT_STATUS_IS_OK(status)) {
2175 return NT_STATUS_OK;
2179 lsa_CloseTrustedDomainEx
2181 static NTSTATUS dcesrv_lsa_CloseTrustedDomainEx(struct dcesrv_call_state *dce_call,
2182 TALLOC_CTX *mem_ctx,
2183 struct lsa_CloseTrustedDomainEx *r)
2185 /* The result of a bad hair day from an IDL programmer? Not
2186 * implmented in Win2k3. You should always just lsa_Close
2188 return NT_STATUS_NOT_IMPLEMENTED;
2193 comparison function for sorting lsa_DomainInformation array
2195 static int compare_DomainInfo(struct lsa_DomainInfo *e1, struct lsa_DomainInfo *e2)
2197 return strcasecmp_m(e1->name.string, e2->name.string);
2203 static NTSTATUS dcesrv_lsa_EnumTrustDom(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2204 struct lsa_EnumTrustDom *r)
2206 struct dcesrv_handle *policy_handle;
2207 struct lsa_DomainInfo *entries;
2208 struct lsa_policy_state *policy_state;
2209 struct ldb_message **domains;
2210 const char *attrs[] = {
2212 "securityIdentifier",
2219 *r->out.resume_handle = 0;
2221 r->out.domains->domains = NULL;
2222 r->out.domains->count = 0;
2224 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2226 policy_state = policy_handle->data;
2228 /* search for all users in this domain. This could possibly be cached and
2229 resumed based on resume_key */
2230 count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
2231 "objectclass=trustedDomain");
2233 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2236 /* convert to lsa_TrustInformation format */
2237 entries = talloc_array(mem_ctx, struct lsa_DomainInfo, count);
2239 return NT_STATUS_NO_MEMORY;
2241 for (i=0;i<count;i++) {
2242 entries[i].sid = samdb_result_dom_sid(mem_ctx, domains[i], "securityIdentifier");
2243 entries[i].name.string = ldb_msg_find_attr_as_string(domains[i], "flatname", NULL);
2246 /* sort the results by name */
2247 TYPESAFE_QSORT(entries, count, compare_DomainInfo);
2249 if (*r->in.resume_handle >= count) {
2250 *r->out.resume_handle = -1;
2252 return NT_STATUS_NO_MORE_ENTRIES;
2255 /* return the rest, limit by max_size. Note that we
2256 use the w2k3 element size value of 60 */
2257 r->out.domains->count = count - *r->in.resume_handle;
2258 r->out.domains->count = MIN(r->out.domains->count,
2259 1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_MULTIPLIER));
2261 r->out.domains->domains = entries + *r->in.resume_handle;
2262 r->out.domains->count = r->out.domains->count;
2264 if (r->out.domains->count < count - *r->in.resume_handle) {
2265 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2266 return STATUS_MORE_ENTRIES;
2269 /* according to MS-LSAD 3.1.4.7.8 output resume handle MUST
2270 * always be larger than the previous input resume handle, in
2271 * particular when hitting the last query it is vital to set the
2272 * resume handle correctly to avoid infinite client loops, as
2273 * seen e.g. with Windows XP SP3 when resume handle is 0 and
2274 * status is NT_STATUS_OK - gd */
2276 *r->out.resume_handle = (uint32_t)-1;
2278 return NT_STATUS_OK;
2282 comparison function for sorting lsa_DomainInformation array
2284 static int compare_TrustDomainInfoInfoEx(struct lsa_TrustDomainInfoInfoEx *e1, struct lsa_TrustDomainInfoInfoEx *e2)
2286 return strcasecmp_m(e1->netbios_name.string, e2->netbios_name.string);
2290 lsa_EnumTrustedDomainsEx
2292 static NTSTATUS dcesrv_lsa_EnumTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2293 struct lsa_EnumTrustedDomainsEx *r)
2295 struct dcesrv_handle *policy_handle;
2296 struct lsa_TrustDomainInfoInfoEx *entries;
2297 struct lsa_policy_state *policy_state;
2298 struct ldb_message **domains;
2299 const char *attrs[] = {
2302 "securityIdentifier",
2312 *r->out.resume_handle = 0;
2314 r->out.domains->domains = NULL;
2315 r->out.domains->count = 0;
2317 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2319 policy_state = policy_handle->data;
2321 /* search for all users in this domain. This could possibly be cached and
2322 resumed based on resume_key */
2323 count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
2324 "objectclass=trustedDomain");
2326 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2329 /* convert to lsa_DomainInformation format */
2330 entries = talloc_array(mem_ctx, struct lsa_TrustDomainInfoInfoEx, count);
2332 return NT_STATUS_NO_MEMORY;
2334 for (i=0;i<count;i++) {
2335 nt_status = fill_trust_domain_ex(mem_ctx, domains[i], &entries[i]);
2336 if (!NT_STATUS_IS_OK(nt_status)) {
2341 /* sort the results by name */
2342 TYPESAFE_QSORT(entries, count, compare_TrustDomainInfoInfoEx);
2344 if (*r->in.resume_handle >= count) {
2345 *r->out.resume_handle = -1;
2347 return NT_STATUS_NO_MORE_ENTRIES;
2350 /* return the rest, limit by max_size. Note that we
2351 use the w2k3 element size value of 60 */
2352 r->out.domains->count = count - *r->in.resume_handle;
2353 r->out.domains->count = MIN(r->out.domains->count,
2354 1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_EX_MULTIPLIER));
2356 r->out.domains->domains = entries + *r->in.resume_handle;
2357 r->out.domains->count = r->out.domains->count;
2359 if (r->out.domains->count < count - *r->in.resume_handle) {
2360 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2361 return STATUS_MORE_ENTRIES;
2364 return NT_STATUS_OK;
2371 static NTSTATUS dcesrv_lsa_OpenAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2372 struct lsa_OpenAccount *r)
2374 struct dcesrv_handle *h, *ah;
2375 struct lsa_policy_state *state;
2376 struct lsa_account_state *astate;
2378 ZERO_STRUCTP(r->out.acct_handle);
2380 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2384 astate = talloc(dce_call->conn, struct lsa_account_state);
2385 if (astate == NULL) {
2386 return NT_STATUS_NO_MEMORY;
2389 astate->account_sid = dom_sid_dup(astate, r->in.sid);
2390 if (astate->account_sid == NULL) {
2391 talloc_free(astate);
2392 return NT_STATUS_NO_MEMORY;
2395 astate->policy = talloc_reference(astate, state);
2396 astate->access_mask = r->in.access_mask;
2398 ah = dcesrv_handle_new(dce_call->context, LSA_HANDLE_ACCOUNT);
2400 talloc_free(astate);
2401 return NT_STATUS_NO_MEMORY;
2404 ah->data = talloc_steal(ah, astate);
2406 *r->out.acct_handle = ah->wire_handle;
2408 return NT_STATUS_OK;
2413 lsa_EnumPrivsAccount
2415 static NTSTATUS dcesrv_lsa_EnumPrivsAccount(struct dcesrv_call_state *dce_call,
2416 TALLOC_CTX *mem_ctx,
2417 struct lsa_EnumPrivsAccount *r)
2419 struct dcesrv_handle *h;
2420 struct lsa_account_state *astate;
2423 struct ldb_message **res;
2424 const char * const attrs[] = { "privilege", NULL};
2425 struct ldb_message_element *el;
2427 struct lsa_PrivilegeSet *privs;
2429 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2433 privs = talloc(mem_ctx, struct lsa_PrivilegeSet);
2434 if (privs == NULL) {
2435 return NT_STATUS_NO_MEMORY;
2441 *r->out.privs = privs;
2443 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
2444 if (sidstr == NULL) {
2445 return NT_STATUS_NO_MEMORY;
2448 ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs,
2449 "objectSid=%s", sidstr);
2451 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2454 return NT_STATUS_OK;
2457 el = ldb_msg_find_element(res[0], "privilege");
2458 if (el == NULL || el->num_values == 0) {
2459 return NT_STATUS_OK;
2462 privs->set = talloc_array(privs,
2463 struct lsa_LUIDAttribute, el->num_values);
2464 if (privs->set == NULL) {
2465 return NT_STATUS_NO_MEMORY;
2469 for (i=0;i<el->num_values;i++) {
2470 int id = sec_privilege_id((const char *)el->values[i].data);
2471 if (id == SEC_PRIV_INVALID) {
2472 /* Perhaps an account right, not a privilege */
2475 privs->set[j].attribute = 0;
2476 privs->set[j].luid.low = id;
2477 privs->set[j].luid.high = 0;
2483 return NT_STATUS_OK;
2487 lsa_EnumAccountRights
2489 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call,
2490 TALLOC_CTX *mem_ctx,
2491 struct lsa_EnumAccountRights *r)
2493 struct dcesrv_handle *h;
2494 struct lsa_policy_state *state;
2497 struct ldb_message **res;
2498 const char * const attrs[] = { "privilege", NULL};
2500 struct ldb_message_element *el;
2502 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2506 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, r->in.sid);
2507 if (sidstr == NULL) {
2508 return NT_STATUS_NO_MEMORY;
2511 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
2512 "(&(objectSid=%s)(privilege=*))", sidstr);
2514 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2517 DEBUG(3, ("searching for account rights for SID: %s failed: %s",
2518 dom_sid_string(mem_ctx, r->in.sid),
2519 ldb_errstring(state->pdb)));
2520 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2523 el = ldb_msg_find_element(res[0], "privilege");
2524 if (el == NULL || el->num_values == 0) {
2525 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2528 r->out.rights->count = el->num_values;
2529 r->out.rights->names = talloc_array(r->out.rights,
2530 struct lsa_StringLarge, r->out.rights->count);
2531 if (r->out.rights->names == NULL) {
2532 return NT_STATUS_NO_MEMORY;
2535 for (i=0;i<el->num_values;i++) {
2536 r->out.rights->names[i].string = (const char *)el->values[i].data;
2539 return NT_STATUS_OK;
2545 helper for lsa_AddAccountRights and lsa_RemoveAccountRights
2547 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
2548 TALLOC_CTX *mem_ctx,
2549 struct lsa_policy_state *state,
2551 struct dom_sid *sid,
2552 const struct lsa_RightSet *rights)
2554 const char *sidstr, *sidndrstr;
2555 struct ldb_message *msg;
2556 struct ldb_message_element *el;
2559 struct lsa_EnumAccountRights r2;
2562 if (security_session_user_level(dce_call->conn->auth_state.session_info, NULL) <
2563 SECURITY_ADMINISTRATOR) {
2564 DEBUG(0,("lsa_AddRemoveAccount refused for supplied security token\n"));
2565 return NT_STATUS_ACCESS_DENIED;
2568 msg = ldb_msg_new(mem_ctx);
2570 return NT_STATUS_NO_MEMORY;
2573 sidndrstr = ldap_encode_ndr_dom_sid(msg, sid);
2574 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sidndrstr, msg);
2576 sidstr = dom_sid_string(msg, sid);
2577 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sidstr, msg);
2579 dnstr = talloc_asprintf(msg, "sid=%s", sidstr);
2580 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(dnstr, msg);
2582 msg->dn = ldb_dn_new(msg, state->pdb, dnstr);
2583 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(msg->dn, msg);
2585 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2588 r2.in.handle = &state->handle->wire_handle;
2590 r2.out.rights = talloc(mem_ctx, struct lsa_RightSet);
2592 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
2593 if (!NT_STATUS_IS_OK(status)) {
2594 ZERO_STRUCTP(r2.out.rights);
2598 for (i=0;i<rights->count;i++) {
2599 if (sec_privilege_id(rights->names[i].string) == SEC_PRIV_INVALID) {
2600 if (sec_right_bit(rights->names[i].string) == 0) {
2602 return NT_STATUS_NO_SUCH_PRIVILEGE;
2606 return NT_STATUS_NO_SUCH_PRIVILEGE;
2609 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2611 for (j=0;j<r2.out.rights->count;j++) {
2612 if (strcasecmp_m(r2.out.rights->names[j].string,
2613 rights->names[i].string) == 0) {
2617 if (j != r2.out.rights->count) continue;
2620 ret = ldb_msg_add_string(msg, "privilege", rights->names[i].string);
2621 if (ret != LDB_SUCCESS) {
2623 return NT_STATUS_NO_MEMORY;
2627 el = ldb_msg_find_element(msg, "privilege");
2630 return NT_STATUS_OK;
2633 el->flags = ldb_flag;
2635 ret = ldb_modify(state->pdb, msg);
2636 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
2637 if (samdb_msg_add_dom_sid(state->pdb, msg, msg, "objectSid", sid) != LDB_SUCCESS) {
2639 return NT_STATUS_NO_MEMORY;
2641 ldb_msg_add_string(msg, "comment", "added via LSA");
2642 ret = ldb_add(state->pdb, msg);
2644 if (ret != LDB_SUCCESS) {
2645 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE && ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
2647 return NT_STATUS_OK;
2649 DEBUG(3, ("Could not %s attributes from %s: %s",
2650 LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE ? "delete" : "add",
2651 ldb_dn_get_linearized(msg->dn), ldb_errstring(state->pdb)));
2653 return NT_STATUS_UNEXPECTED_IO_ERROR;
2657 return NT_STATUS_OK;
2661 lsa_AddPrivilegesToAccount
2663 static NTSTATUS dcesrv_lsa_AddPrivilegesToAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2664 struct lsa_AddPrivilegesToAccount *r)
2666 struct lsa_RightSet rights;
2667 struct dcesrv_handle *h;
2668 struct lsa_account_state *astate;
2671 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2675 rights.count = r->in.privs->count;
2676 rights.names = talloc_array(mem_ctx, struct lsa_StringLarge, rights.count);
2677 if (rights.names == NULL) {
2678 return NT_STATUS_NO_MEMORY;
2680 for (i=0;i<rights.count;i++) {
2681 int id = r->in.privs->set[i].luid.low;
2682 if (r->in.privs->set[i].luid.high) {
2683 return NT_STATUS_NO_SUCH_PRIVILEGE;
2685 rights.names[i].string = sec_privilege_name(id);
2686 if (rights.names[i].string == NULL) {
2687 return NT_STATUS_NO_SUCH_PRIVILEGE;
2691 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
2692 LDB_FLAG_MOD_ADD, astate->account_sid,
2698 lsa_RemovePrivilegesFromAccount
2700 static NTSTATUS dcesrv_lsa_RemovePrivilegesFromAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2701 struct lsa_RemovePrivilegesFromAccount *r)
2703 struct lsa_RightSet *rights;
2704 struct dcesrv_handle *h;
2705 struct lsa_account_state *astate;
2708 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2712 rights = talloc(mem_ctx, struct lsa_RightSet);
2714 if (r->in.remove_all == 1 &&
2715 r->in.privs == NULL) {
2716 struct lsa_EnumAccountRights r2;
2719 r2.in.handle = &astate->policy->handle->wire_handle;
2720 r2.in.sid = astate->account_sid;
2721 r2.out.rights = rights;
2723 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
2724 if (!NT_STATUS_IS_OK(status)) {
2728 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
2729 LDB_FLAG_MOD_DELETE, astate->account_sid,
2733 if (r->in.remove_all != 0) {
2734 return NT_STATUS_INVALID_PARAMETER;
2737 rights->count = r->in.privs->count;
2738 rights->names = talloc_array(mem_ctx, struct lsa_StringLarge, rights->count);
2739 if (rights->names == NULL) {
2740 return NT_STATUS_NO_MEMORY;
2742 for (i=0;i<rights->count;i++) {
2743 int id = r->in.privs->set[i].luid.low;
2744 if (r->in.privs->set[i].luid.high) {
2745 return NT_STATUS_NO_SUCH_PRIVILEGE;
2747 rights->names[i].string = sec_privilege_name(id);
2748 if (rights->names[i].string == NULL) {
2749 return NT_STATUS_NO_SUCH_PRIVILEGE;
2753 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
2754 LDB_FLAG_MOD_DELETE, astate->account_sid,
2760 lsa_GetQuotasForAccount
2762 static NTSTATUS dcesrv_lsa_GetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2763 struct lsa_GetQuotasForAccount *r)
2765 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2770 lsa_SetQuotasForAccount
2772 static NTSTATUS dcesrv_lsa_SetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2773 struct lsa_SetQuotasForAccount *r)
2775 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2780 lsa_GetSystemAccessAccount
2782 static NTSTATUS dcesrv_lsa_GetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2783 struct lsa_GetSystemAccessAccount *r)
2785 struct dcesrv_handle *h;
2786 struct lsa_account_state *astate;
2789 struct ldb_message **res;
2790 const char * const attrs[] = { "privilege", NULL};
2791 struct ldb_message_element *el;
2794 *(r->out.access_mask) = 0x00000000;
2796 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2800 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
2801 if (sidstr == NULL) {
2802 return NT_STATUS_NO_MEMORY;
2805 ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs,
2806 "objectSid=%s", sidstr);
2808 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2811 return NT_STATUS_OK;
2814 el = ldb_msg_find_element(res[0], "privilege");
2815 if (el == NULL || el->num_values == 0) {
2816 return NT_STATUS_OK;
2819 for (i=0;i<el->num_values;i++) {
2820 uint32_t right_bit = sec_right_bit((const char *)el->values[i].data);
2821 if (right_bit == 0) {
2822 /* Perhaps an privilege, not a right */
2825 *(r->out.access_mask) |= right_bit;
2828 return NT_STATUS_OK;
2833 lsa_SetSystemAccessAccount
2835 static NTSTATUS dcesrv_lsa_SetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2836 struct lsa_SetSystemAccessAccount *r)
2838 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2845 static NTSTATUS dcesrv_lsa_CreateSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2846 struct lsa_CreateSecret *r)
2848 struct dcesrv_handle *policy_handle;
2849 struct lsa_policy_state *policy_state;
2850 struct lsa_secret_state *secret_state;
2851 struct dcesrv_handle *handle;
2852 struct ldb_message **msgs, *msg;
2853 const char *attrs[] = {
2861 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2862 ZERO_STRUCTP(r->out.sec_handle);
2864 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
2866 case SECURITY_SYSTEM:
2867 case SECURITY_ADMINISTRATOR:
2870 /* Users and annonymous are not allowed create secrets */
2871 return NT_STATUS_ACCESS_DENIED;
2874 policy_state = policy_handle->data;
2876 if (!r->in.name.string) {
2877 return NT_STATUS_INVALID_PARAMETER;
2880 secret_state = talloc(mem_ctx, struct lsa_secret_state);
2881 NT_STATUS_HAVE_NO_MEMORY(secret_state);
2882 secret_state->policy = policy_state;
2884 msg = ldb_msg_new(mem_ctx);
2886 return NT_STATUS_NO_MEMORY;
2889 if (strncmp("G$", r->in.name.string, 2) == 0) {
2892 secret_state->global = true;
2894 name = &r->in.name.string[2];
2895 if (strlen(name) == 0) {
2896 return NT_STATUS_INVALID_PARAMETER;
2899 name2 = talloc_asprintf(mem_ctx, "%s Secret",
2900 ldb_binary_encode_string(mem_ctx, name));
2901 NT_STATUS_HAVE_NO_MEMORY(name2);
2903 /* We need to connect to the database as system, as this is one
2904 * of the rare RPC calls that must read the secrets (and this
2905 * is denied otherwise) */
2906 secret_state->sam_ldb = talloc_reference(secret_state,
2907 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));
2908 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
2910 /* search for the secret record */
2911 ret = gendb_search(secret_state->sam_ldb,
2912 mem_ctx, policy_state->system_dn, &msgs, attrs,
2913 "(&(cn=%s)(objectclass=secret))",
2916 return NT_STATUS_OBJECT_NAME_COLLISION;
2920 DEBUG(0,("Failure searching for CN=%s: %s\n",
2921 name2, ldb_errstring(secret_state->sam_ldb)));
2922 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2925 msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
2926 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
2927 if (!ldb_dn_add_child_fmt(msg->dn, "cn=%s", name2)) {
2928 return NT_STATUS_NO_MEMORY;
2931 ret = ldb_msg_add_string(msg, "cn", name2);
2932 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
2934 secret_state->global = false;
2936 name = r->in.name.string;
2937 if (strlen(name) == 0) {
2938 return NT_STATUS_INVALID_PARAMETER;
2941 secret_state->sam_ldb = talloc_reference(secret_state,
2942 secrets_db_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
2943 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
2945 /* search for the secret record */
2946 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
2947 ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
2949 "(&(cn=%s)(objectclass=secret))",
2950 ldb_binary_encode_string(mem_ctx, name));
2952 return NT_STATUS_OBJECT_NAME_COLLISION;
2956 DEBUG(0,("Failure searching for CN=%s: %s\n",
2957 name, ldb_errstring(secret_state->sam_ldb)));
2958 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2961 msg->dn = ldb_dn_new_fmt(mem_ctx, secret_state->sam_ldb,
2962 "cn=%s,cn=LSA Secrets", name);
2963 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
2964 ret = ldb_msg_add_string(msg, "cn", name);
2965 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
2968 ret = ldb_msg_add_string(msg, "objectClass", "secret");
2969 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
2971 secret_state->secret_dn = talloc_reference(secret_state, msg->dn);
2972 NT_STATUS_HAVE_NO_MEMORY(secret_state->secret_dn);
2974 /* create the secret */
2975 ret = ldb_add(secret_state->sam_ldb, msg);
2976 if (ret != LDB_SUCCESS) {
2977 DEBUG(0,("Failed to create secret record %s: %s\n",
2978 ldb_dn_get_linearized(msg->dn),
2979 ldb_errstring(secret_state->sam_ldb)));
2980 return NT_STATUS_ACCESS_DENIED;
2983 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
2984 NT_STATUS_HAVE_NO_MEMORY(handle);
2986 handle->data = talloc_steal(handle, secret_state);
2988 secret_state->access_mask = r->in.access_mask;
2989 secret_state->policy = talloc_reference(secret_state, policy_state);
2990 NT_STATUS_HAVE_NO_MEMORY(secret_state->policy);
2992 *r->out.sec_handle = handle->wire_handle;
2994 return NT_STATUS_OK;
3001 static NTSTATUS dcesrv_lsa_OpenSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3002 struct lsa_OpenSecret *r)
3004 struct dcesrv_handle *policy_handle;
3006 struct lsa_policy_state *policy_state;
3007 struct lsa_secret_state *secret_state;
3008 struct dcesrv_handle *handle;
3009 struct ldb_message **msgs;
3010 const char *attrs[] = {
3018 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
3019 ZERO_STRUCTP(r->out.sec_handle);
3020 policy_state = policy_handle->data;
3022 if (!r->in.name.string) {
3023 return NT_STATUS_INVALID_PARAMETER;
3026 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3028 case SECURITY_SYSTEM:
3029 case SECURITY_ADMINISTRATOR:
3032 /* Users and annonymous are not allowed to access secrets */
3033 return NT_STATUS_ACCESS_DENIED;
3036 secret_state = talloc(mem_ctx, struct lsa_secret_state);
3037 if (!secret_state) {
3038 return NT_STATUS_NO_MEMORY;
3040 secret_state->policy = policy_state;
3042 if (strncmp("G$", r->in.name.string, 2) == 0) {
3043 name = &r->in.name.string[2];
3044 /* 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) */
3045 secret_state->sam_ldb = talloc_reference(secret_state,
3046 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));
3047 secret_state->global = true;
3049 if (strlen(name) < 1) {
3050 return NT_STATUS_INVALID_PARAMETER;
3053 /* search for the secret record */
3054 ret = gendb_search(secret_state->sam_ldb,
3055 mem_ctx, policy_state->system_dn, &msgs, attrs,
3056 "(&(cn=%s Secret)(objectclass=secret))",
3057 ldb_binary_encode_string(mem_ctx, name));
3059 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3063 DEBUG(0,("Found %d records matching DN %s\n", ret,
3064 ldb_dn_get_linearized(policy_state->system_dn)));
3065 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3069 secret_state->global = false;
3070 secret_state->sam_ldb = talloc_reference(secret_state,
3071 secrets_db_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
3073 name = r->in.name.string;
3074 if (strlen(name) < 1) {
3075 return NT_STATUS_INVALID_PARAMETER;
3078 /* search for the secret record */
3079 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
3080 ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
3082 "(&(cn=%s)(objectclass=secret))",
3083 ldb_binary_encode_string(mem_ctx, name));
3085 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3089 DEBUG(0,("Found %d records matching CN=%s\n",
3090 ret, ldb_binary_encode_string(mem_ctx, name)));
3091 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3095 secret_state->secret_dn = talloc_reference(secret_state, msgs[0]->dn);
3097 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
3099 return NT_STATUS_NO_MEMORY;
3102 handle->data = talloc_steal(handle, secret_state);
3104 secret_state->access_mask = r->in.access_mask;
3105 secret_state->policy = talloc_reference(secret_state, policy_state);
3107 *r->out.sec_handle = handle->wire_handle;
3109 return NT_STATUS_OK;
3116 static NTSTATUS dcesrv_lsa_SetSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3117 struct lsa_SetSecret *r)
3120 struct dcesrv_handle *h;
3121 struct lsa_secret_state *secret_state;
3122 struct ldb_message *msg;
3123 DATA_BLOB session_key;
3124 DATA_BLOB crypt_secret, secret;
3127 NTSTATUS status = NT_STATUS_OK;
3129 struct timeval now = timeval_current();
3130 NTTIME nt_now = timeval_to_nttime(&now);
3132 DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3134 secret_state = h->data;
3136 msg = ldb_msg_new(mem_ctx);
3138 return NT_STATUS_NO_MEMORY;
3141 msg->dn = talloc_reference(mem_ctx, secret_state->secret_dn);
3143 return NT_STATUS_NO_MEMORY;
3145 status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
3146 if (!NT_STATUS_IS_OK(status)) {
3150 if (r->in.old_val) {
3152 crypt_secret.data = r->in.old_val->data;
3153 crypt_secret.length = r->in.old_val->size;
3155 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3156 if (!NT_STATUS_IS_OK(status)) {
3160 val.data = secret.data;
3161 val.length = secret.length;
3164 if (ldb_msg_add_value(msg, "priorValue", &val, NULL) != LDB_SUCCESS) {
3165 return NT_STATUS_NO_MEMORY;
3168 /* set old value mtime */
3169 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3170 mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3171 return NT_STATUS_NO_MEMORY;
3175 /* If the old value is not set, then migrate the
3176 * current value to the old value */
3177 const struct ldb_val *old_val;
3178 NTTIME last_set_time;
3179 struct ldb_message **res;
3180 const char *attrs[] = {
3186 /* search for the secret record */
3187 ret = gendb_search_dn(secret_state->sam_ldb,mem_ctx,
3188 secret_state->secret_dn, &res, attrs);
3190 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3194 DEBUG(0,("Found %d records matching dn=%s\n", ret,
3195 ldb_dn_get_linearized(secret_state->secret_dn)));
3196 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3199 old_val = ldb_msg_find_ldb_val(res[0], "currentValue");
3200 last_set_time = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
3204 if (ldb_msg_add_value(msg, "priorValue",
3205 old_val, NULL) != LDB_SUCCESS) {
3206 return NT_STATUS_NO_MEMORY;
3209 if (samdb_msg_add_delete(secret_state->sam_ldb,
3210 mem_ctx, msg, "priorValue") != LDB_SUCCESS) {
3211 return NT_STATUS_NO_MEMORY;
3216 /* set old value mtime */
3217 if (ldb_msg_find_ldb_val(res[0], "lastSetTime")) {
3218 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3219 mem_ctx, msg, "priorSetTime", last_set_time) != LDB_SUCCESS) {
3220 return NT_STATUS_NO_MEMORY;
3223 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3224 mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3225 return NT_STATUS_NO_MEMORY;
3230 if (r->in.new_val) {
3232 crypt_secret.data = r->in.new_val->data;
3233 crypt_secret.length = r->in.new_val->size;
3235 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3236 if (!NT_STATUS_IS_OK(status)) {
3240 val.data = secret.data;
3241 val.length = secret.length;
3244 if (ldb_msg_add_value(msg, "currentValue", &val, NULL) != LDB_SUCCESS) {
3245 return NT_STATUS_NO_MEMORY;
3248 /* set new value mtime */
3249 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3250 mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3251 return NT_STATUS_NO_MEMORY;
3255 /* NULL out the NEW value */
3256 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3257 mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3258 return NT_STATUS_NO_MEMORY;
3260 if (samdb_msg_add_delete(secret_state->sam_ldb,
3261 mem_ctx, msg, "currentValue") != LDB_SUCCESS) {
3262 return NT_STATUS_NO_MEMORY;
3266 /* modify the samdb record */
3267 ret = dsdb_replace(secret_state->sam_ldb, msg, 0);
3268 if (ret != LDB_SUCCESS) {
3269 return dsdb_ldb_err_to_ntstatus(ret);
3272 return NT_STATUS_OK;
3279 static NTSTATUS dcesrv_lsa_QuerySecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3280 struct lsa_QuerySecret *r)
3282 struct dcesrv_handle *h;
3283 struct lsa_secret_state *secret_state;
3284 struct ldb_message *msg;
3285 DATA_BLOB session_key;
3286 DATA_BLOB crypt_secret, secret;
3288 struct ldb_message **res;
3289 const char *attrs[] = {
3299 DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3301 /* Ensure user is permitted to read this... */
3302 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3304 case SECURITY_SYSTEM:
3305 case SECURITY_ADMINISTRATOR:
3308 /* Users and annonymous are not allowed to read secrets */
3309 return NT_STATUS_ACCESS_DENIED;
3312 secret_state = h->data;
3314 /* pull all the user attributes */
3315 ret = gendb_search_dn(secret_state->sam_ldb, mem_ctx,
3316 secret_state->secret_dn, &res, attrs);
3318 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3322 nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
3323 if (!NT_STATUS_IS_OK(nt_status)) {
3327 if (r->in.old_val) {
3328 const struct ldb_val *prior_val;
3329 r->out.old_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3330 if (!r->out.old_val) {
3331 return NT_STATUS_NO_MEMORY;
3333 prior_val = ldb_msg_find_ldb_val(res[0], "priorValue");
3335 if (prior_val && prior_val->length) {
3336 secret.data = prior_val->data;
3337 secret.length = prior_val->length;
3340 crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3341 if (!crypt_secret.length) {
3342 return NT_STATUS_NO_MEMORY;
3344 r->out.old_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3345 if (!r->out.old_val->buf) {
3346 return NT_STATUS_NO_MEMORY;
3348 r->out.old_val->buf->size = crypt_secret.length;
3349 r->out.old_val->buf->length = crypt_secret.length;
3350 r->out.old_val->buf->data = crypt_secret.data;
3354 if (r->in.old_mtime) {
3355 r->out.old_mtime = talloc(mem_ctx, NTTIME);
3356 if (!r->out.old_mtime) {
3357 return NT_STATUS_NO_MEMORY;
3359 *r->out.old_mtime = ldb_msg_find_attr_as_uint64(res[0], "priorSetTime", 0);
3362 if (r->in.new_val) {
3363 const struct ldb_val *new_val;
3364 r->out.new_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3365 if (!r->out.new_val) {
3366 return NT_STATUS_NO_MEMORY;
3369 new_val = ldb_msg_find_ldb_val(res[0], "currentValue");
3371 if (new_val && new_val->length) {
3372 secret.data = new_val->data;
3373 secret.length = new_val->length;
3376 crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3377 if (!crypt_secret.length) {
3378 return NT_STATUS_NO_MEMORY;
3380 r->out.new_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3381 if (!r->out.new_val->buf) {
3382 return NT_STATUS_NO_MEMORY;
3384 r->out.new_val->buf->length = crypt_secret.length;
3385 r->out.new_val->buf->size = crypt_secret.length;
3386 r->out.new_val->buf->data = crypt_secret.data;
3390 if (r->in.new_mtime) {
3391 r->out.new_mtime = talloc(mem_ctx, NTTIME);
3392 if (!r->out.new_mtime) {
3393 return NT_STATUS_NO_MEMORY;
3395 *r->out.new_mtime = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
3398 return NT_STATUS_OK;
3405 static NTSTATUS dcesrv_lsa_LookupPrivValue(struct dcesrv_call_state *dce_call,
3406 TALLOC_CTX *mem_ctx,
3407 struct lsa_LookupPrivValue *r)
3409 struct dcesrv_handle *h;
3410 struct lsa_policy_state *state;
3413 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3417 id = sec_privilege_id(r->in.name->string);
3418 if (id == SEC_PRIV_INVALID) {
3419 return NT_STATUS_NO_SUCH_PRIVILEGE;
3422 r->out.luid->low = id;
3423 r->out.luid->high = 0;
3425 return NT_STATUS_OK;
3432 static NTSTATUS dcesrv_lsa_LookupPrivName(struct dcesrv_call_state *dce_call,
3433 TALLOC_CTX *mem_ctx,
3434 struct lsa_LookupPrivName *r)
3436 struct dcesrv_handle *h;
3437 struct lsa_policy_state *state;
3438 struct lsa_StringLarge *name;
3439 const char *privname;
3441 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3445 if (r->in.luid->high != 0) {
3446 return NT_STATUS_NO_SUCH_PRIVILEGE;
3449 privname = sec_privilege_name(r->in.luid->low);
3450 if (privname == NULL) {
3451 return NT_STATUS_NO_SUCH_PRIVILEGE;
3454 name = talloc(mem_ctx, struct lsa_StringLarge);
3456 return NT_STATUS_NO_MEMORY;
3459 name->string = privname;
3461 *r->out.name = name;
3463 return NT_STATUS_OK;
3468 lsa_LookupPrivDisplayName
3470 static NTSTATUS dcesrv_lsa_LookupPrivDisplayName(struct dcesrv_call_state *dce_call,
3471 TALLOC_CTX *mem_ctx,
3472 struct lsa_LookupPrivDisplayName *r)
3474 struct dcesrv_handle *h;
3475 struct lsa_policy_state *state;
3476 struct lsa_StringLarge *disp_name = NULL;
3477 enum sec_privilege id;
3479 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3483 id = sec_privilege_id(r->in.name->string);
3484 if (id == SEC_PRIV_INVALID) {
3485 return NT_STATUS_NO_SUCH_PRIVILEGE;
3488 disp_name = talloc(mem_ctx, struct lsa_StringLarge);
3489 if (disp_name == NULL) {
3490 return NT_STATUS_NO_MEMORY;
3493 disp_name->string = sec_privilege_display_name(id, &r->in.language_id);
3494 if (disp_name->string == NULL) {
3495 return NT_STATUS_INTERNAL_ERROR;
3498 *r->out.disp_name = disp_name;
3499 *r->out.returned_language_id = 0;
3501 return NT_STATUS_OK;
3506 lsa_EnumAccountsWithUserRight
3508 static NTSTATUS dcesrv_lsa_EnumAccountsWithUserRight(struct dcesrv_call_state *dce_call,
3509 TALLOC_CTX *mem_ctx,
3510 struct lsa_EnumAccountsWithUserRight *r)
3512 struct dcesrv_handle *h;
3513 struct lsa_policy_state *state;
3515 struct ldb_message **res;
3516 const char * const attrs[] = { "objectSid", NULL};
3517 const char *privname;
3519 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3523 if (r->in.name == NULL) {
3524 return NT_STATUS_NO_SUCH_PRIVILEGE;
3527 privname = r->in.name->string;
3528 if (sec_privilege_id(privname) == SEC_PRIV_INVALID && sec_right_bit(privname) == 0) {
3529 return NT_STATUS_NO_SUCH_PRIVILEGE;
3532 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
3533 "privilege=%s", privname);
3535 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3538 return NT_STATUS_NO_MORE_ENTRIES;
3541 r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, ret);
3542 if (r->out.sids->sids == NULL) {
3543 return NT_STATUS_NO_MEMORY;
3545 for (i=0;i<ret;i++) {
3546 r->out.sids->sids[i].sid = samdb_result_dom_sid(r->out.sids->sids,
3547 res[i], "objectSid");
3548 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
3550 r->out.sids->num_sids = ret;
3552 return NT_STATUS_OK;
3557 lsa_AddAccountRights
3559 static NTSTATUS dcesrv_lsa_AddAccountRights(struct dcesrv_call_state *dce_call,
3560 TALLOC_CTX *mem_ctx,
3561 struct lsa_AddAccountRights *r)
3563 struct dcesrv_handle *h;
3564 struct lsa_policy_state *state;
3566 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3570 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3572 r->in.sid, r->in.rights);
3577 lsa_RemoveAccountRights
3579 static NTSTATUS dcesrv_lsa_RemoveAccountRights(struct dcesrv_call_state *dce_call,
3580 TALLOC_CTX *mem_ctx,
3581 struct lsa_RemoveAccountRights *r)
3583 struct dcesrv_handle *h;
3584 struct lsa_policy_state *state;
3586 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3590 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3591 LDB_FLAG_MOD_DELETE,
3592 r->in.sid, r->in.rights);
3597 lsa_StorePrivateData
3599 static NTSTATUS dcesrv_lsa_StorePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3600 struct lsa_StorePrivateData *r)
3602 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3607 lsa_RetrievePrivateData
3609 static NTSTATUS dcesrv_lsa_RetrievePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3610 struct lsa_RetrievePrivateData *r)
3612 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3619 static NTSTATUS dcesrv_lsa_GetUserName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3620 struct lsa_GetUserName *r)
3622 NTSTATUS status = NT_STATUS_OK;
3623 const char *account_name;
3624 const char *authority_name;
3625 struct lsa_String *_account_name;
3626 struct lsa_String *_authority_name = NULL;
3628 /* this is what w2k3 does */
3629 r->out.account_name = r->in.account_name;
3630 r->out.authority_name = r->in.authority_name;
3632 if (r->in.account_name
3633 && *r->in.account_name
3634 /* && *(*r->in.account_name)->string */
3636 return NT_STATUS_INVALID_PARAMETER;
3639 if (r->in.authority_name
3640 && *r->in.authority_name
3641 /* && *(*r->in.authority_name)->string */
3643 return NT_STATUS_INVALID_PARAMETER;
3646 account_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->info->account_name);
3647 authority_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->info->domain_name);
3649 _account_name = talloc(mem_ctx, struct lsa_String);
3650 NT_STATUS_HAVE_NO_MEMORY(_account_name);
3651 _account_name->string = account_name;
3653 if (r->in.authority_name) {
3654 _authority_name = talloc(mem_ctx, struct lsa_String);
3655 NT_STATUS_HAVE_NO_MEMORY(_authority_name);
3656 _authority_name->string = authority_name;
3659 *r->out.account_name = _account_name;
3660 if (r->out.authority_name) {
3661 *r->out.authority_name = _authority_name;
3670 static NTSTATUS dcesrv_lsa_SetInfoPolicy2(struct dcesrv_call_state *dce_call,
3671 TALLOC_CTX *mem_ctx,
3672 struct lsa_SetInfoPolicy2 *r)
3674 /* need to support these */
3675 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3679 lsa_QueryDomainInformationPolicy
3681 static NTSTATUS dcesrv_lsa_QueryDomainInformationPolicy(struct dcesrv_call_state *dce_call,
3682 TALLOC_CTX *mem_ctx,
3683 struct lsa_QueryDomainInformationPolicy *r)
3685 union lsa_DomainInformationPolicy *info;
3687 info = talloc_zero(r->out.info, union lsa_DomainInformationPolicy);
3689 return NT_STATUS_NO_MEMORY;
3692 switch (r->in.level) {
3693 case LSA_DOMAIN_INFO_POLICY_EFS:
3695 *r->out.info = NULL;
3696 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3697 case LSA_DOMAIN_INFO_POLICY_KERBEROS:
3699 struct lsa_DomainInfoKerberos *k = &info->kerberos_info;
3700 struct smb_krb5_context *smb_krb5_context;
3701 int ret = smb_krb5_init_context(mem_ctx,
3702 dce_call->event_ctx,
3703 dce_call->conn->dce_ctx->lp_ctx,
3707 *r->out.info = NULL;
3708 return NT_STATUS_INTERNAL_ERROR;
3710 kdc_get_policy(dce_call->conn->dce_ctx->lp_ctx,
3713 talloc_free(smb_krb5_context);
3714 *r->out.info = info;
3715 return NT_STATUS_OK;
3719 *r->out.info = NULL;
3720 return NT_STATUS_INVALID_INFO_CLASS;
3725 lsa_SetDomInfoPolicy
3727 static NTSTATUS dcesrv_lsa_SetDomainInformationPolicy(struct dcesrv_call_state *dce_call,
3728 TALLOC_CTX *mem_ctx,
3729 struct lsa_SetDomainInformationPolicy *r)
3731 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3737 static NTSTATUS dcesrv_lsa_TestCall(struct dcesrv_call_state *dce_call,
3738 TALLOC_CTX *mem_ctx,
3739 struct lsa_TestCall *r)
3741 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3747 static NTSTATUS dcesrv_lsa_CREDRWRITE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3748 struct lsa_CREDRWRITE *r)
3750 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3757 static NTSTATUS dcesrv_lsa_CREDRREAD(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3758 struct lsa_CREDRREAD *r)
3760 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3767 static NTSTATUS dcesrv_lsa_CREDRENUMERATE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3768 struct lsa_CREDRENUMERATE *r)
3770 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3775 lsa_CREDRWRITEDOMAINCREDENTIALS
3777 static NTSTATUS dcesrv_lsa_CREDRWRITEDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3778 struct lsa_CREDRWRITEDOMAINCREDENTIALS *r)
3780 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3785 lsa_CREDRREADDOMAINCREDENTIALS
3787 static NTSTATUS dcesrv_lsa_CREDRREADDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3788 struct lsa_CREDRREADDOMAINCREDENTIALS *r)
3790 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3797 static NTSTATUS dcesrv_lsa_CREDRDELETE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3798 struct lsa_CREDRDELETE *r)
3800 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3805 lsa_CREDRGETTARGETINFO
3807 static NTSTATUS dcesrv_lsa_CREDRGETTARGETINFO(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3808 struct lsa_CREDRGETTARGETINFO *r)
3810 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3815 lsa_CREDRPROFILELOADED
3817 static NTSTATUS dcesrv_lsa_CREDRPROFILELOADED(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3818 struct lsa_CREDRPROFILELOADED *r)
3820 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3825 lsa_CREDRGETSESSIONTYPES
3827 static NTSTATUS dcesrv_lsa_CREDRGETSESSIONTYPES(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3828 struct lsa_CREDRGETSESSIONTYPES *r)
3830 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3835 lsa_LSARREGISTERAUDITEVENT
3837 static NTSTATUS dcesrv_lsa_LSARREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3838 struct lsa_LSARREGISTERAUDITEVENT *r)
3840 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3845 lsa_LSARGENAUDITEVENT
3847 static NTSTATUS dcesrv_lsa_LSARGENAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3848 struct lsa_LSARGENAUDITEVENT *r)
3850 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3855 lsa_LSARUNREGISTERAUDITEVENT
3857 static NTSTATUS dcesrv_lsa_LSARUNREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3858 struct lsa_LSARUNREGISTERAUDITEVENT *r)
3860 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3865 lsa_lsaRQueryForestTrustInformation
3867 static NTSTATUS dcesrv_lsa_lsaRQueryForestTrustInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3868 struct lsa_lsaRQueryForestTrustInformation *r)
3870 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3873 #define DNS_CMP_MATCH 0
3874 #define DNS_CMP_FIRST_IS_CHILD 1
3875 #define DNS_CMP_SECOND_IS_CHILD 2
3876 #define DNS_CMP_NO_MATCH 3
3878 /* this function assumes names are well formed DNS names.
3879 * it doesn't validate them */
3880 static int dns_cmp(const char *s1, size_t l1,
3881 const char *s2, size_t l2)
3883 const char *p1, *p2;
3888 if (strcasecmp_m(s1, s2) == 0) {
3889 return DNS_CMP_MATCH;
3891 return DNS_CMP_NO_MATCH;
3899 cret = DNS_CMP_FIRST_IS_CHILD;
3905 cret = DNS_CMP_SECOND_IS_CHILD;
3908 if (p1[t1 - t2 - 1] != '.') {
3909 return DNS_CMP_NO_MATCH;
3912 if (strcasecmp_m(&p1[t1 - t2], p2) == 0) {
3916 return DNS_CMP_NO_MATCH;
3919 /* decode all TDOs forest trust info blobs */
3920 static NTSTATUS get_ft_info(TALLOC_CTX *mem_ctx,
3921 struct ldb_message *msg,
3922 struct ForestTrustInfo *info)
3924 const struct ldb_val *ft_blob;
3925 enum ndr_err_code ndr_err;
3927 ft_blob = ldb_msg_find_ldb_val(msg, "msDS-TrustForestTrustInfo");
3928 if (!ft_blob || !ft_blob->data) {
3929 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3931 /* ldb_val is equivalent to DATA_BLOB */
3932 ndr_err = ndr_pull_struct_blob_all(ft_blob, mem_ctx, info,
3933 (ndr_pull_flags_fn_t)ndr_pull_ForestTrustInfo);
3934 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
3935 return NT_STATUS_INVALID_DOMAIN_STATE;
3938 return NT_STATUS_OK;
3941 static NTSTATUS own_ft_info(struct lsa_policy_state *ps,
3942 struct ForestTrustInfo *fti)
3944 struct ForestTrustDataDomainInfo *info;
3945 struct ForestTrustInfoRecord *rec;
3949 fti->records = talloc_array(fti,
3950 struct ForestTrustInfoRecordArmor, 2);
3951 if (!fti->records) {
3952 return NT_STATUS_NO_MEMORY;
3956 rec = &fti->records[0].record;
3960 rec->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
3962 rec->data.name.string = talloc_strdup(fti, ps->forest_dns);
3963 if (!rec->data.name.string) {
3964 return NT_STATUS_NO_MEMORY;
3966 rec->data.name.size = strlen(rec->data.name.string);
3969 rec = &fti->records[1].record;
3973 rec->type = LSA_FOREST_TRUST_DOMAIN_INFO;
3975 info = &rec->data.info;
3977 info->sid = *ps->domain_sid;
3978 info->dns_name.string = talloc_strdup(fti, ps->domain_dns);
3979 if (!info->dns_name.string) {
3980 return NT_STATUS_NO_MEMORY;
3982 info->dns_name.size = strlen(info->dns_name.string);
3983 info->netbios_name.string = talloc_strdup(fti, ps->domain_name);
3984 if (!info->netbios_name.string) {
3985 return NT_STATUS_NO_MEMORY;
3987 info->netbios_name.size = strlen(info->netbios_name.string);
3989 return NT_STATUS_OK;
3992 static NTSTATUS make_ft_info(TALLOC_CTX *mem_ctx,
3993 struct lsa_ForestTrustInformation *lfti,
3994 struct ForestTrustInfo *fti)
3996 struct lsa_ForestTrustRecord *lrec;
3997 struct ForestTrustInfoRecord *rec;
3998 struct lsa_StringLarge *tln;
3999 struct lsa_ForestTrustDomainInfo *info;
4003 fti->count = lfti->count;
4004 fti->records = talloc_array(mem_ctx,
4005 struct ForestTrustInfoRecordArmor,
4007 if (!fti->records) {
4008 return NT_STATUS_NO_MEMORY;
4010 for (i = 0; i < fti->count; i++) {
4011 lrec = lfti->entries[i];
4012 rec = &fti->records[i].record;
4014 rec->flags = lrec->flags;
4015 rec->timestamp = lrec->time;
4016 rec->type = lrec->type;
4018 switch (lrec->type) {
4019 case LSA_FOREST_TRUST_TOP_LEVEL_NAME:
4020 case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
4021 tln = &lrec->forest_trust_data.top_level_name;
4022 rec->data.name.string =
4023 talloc_strdup(mem_ctx, tln->string);
4024 if (!rec->data.name.string) {
4025 return NT_STATUS_NO_MEMORY;
4027 rec->data.name.size = strlen(rec->data.name.string);
4029 case LSA_FOREST_TRUST_DOMAIN_INFO:
4030 info = &lrec->forest_trust_data.domain_info;
4031 rec->data.info.sid = *info->domain_sid;
4032 rec->data.info.dns_name.string =
4033 talloc_strdup(mem_ctx,
4034 info->dns_domain_name.string);
4035 if (!rec->data.info.dns_name.string) {
4036 return NT_STATUS_NO_MEMORY;
4038 rec->data.info.dns_name.size =
4039 strlen(rec->data.info.dns_name.string);
4040 rec->data.info.netbios_name.string =
4041 talloc_strdup(mem_ctx,
4042 info->netbios_domain_name.string);
4043 if (!rec->data.info.netbios_name.string) {
4044 return NT_STATUS_NO_MEMORY;
4046 rec->data.info.netbios_name.size =
4047 strlen(rec->data.info.netbios_name.string);
4050 return NT_STATUS_INVALID_DOMAIN_STATE;
4054 return NT_STATUS_OK;
4057 static NTSTATUS add_collision(struct lsa_ForestTrustCollisionInfo *c_info,
4058 uint32_t idx, uint32_t collision_type,
4059 uint32_t conflict_type, const char *tdo_name);
4061 static NTSTATUS check_ft_info(TALLOC_CTX *mem_ctx,
4062 const char *tdo_name,
4063 struct ForestTrustInfo *tdo_fti,
4064 struct ForestTrustInfo *new_fti,
4065 struct lsa_ForestTrustCollisionInfo *c_info)
4067 struct ForestTrustInfoRecord *nrec;
4068 struct ForestTrustInfoRecord *trec;
4069 const char *dns_name;
4070 const char *nb_name;
4071 struct dom_sid *sid;
4077 uint32_t new_fti_idx;
4079 /* use always TDO type, until we understand when Xref can be used */
4080 uint32_t collision_type = LSA_FOREST_TRUST_COLLISION_TDO;
4088 for (new_fti_idx = 0; new_fti_idx < new_fti->count; new_fti_idx++) {
4090 nrec = &new_fti->records[new_fti_idx].record;
4092 tln_conflict = false;
4093 sid_conflict = false;
4094 nb_conflict = false;
4097 switch (nrec->type) {
4098 case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
4099 /* exclusions do not conflict by definition */
4102 case FOREST_TRUST_TOP_LEVEL_NAME:
4103 dns_name = nrec->data.name.string;
4104 dns_len = nrec->data.name.size;
4107 case LSA_FOREST_TRUST_DOMAIN_INFO:
4108 dns_name = nrec->data.info.dns_name.string;
4109 dns_len = nrec->data.info.dns_name.size;
4110 nb_name = nrec->data.info.netbios_name.string;
4111 nb_len = nrec->data.info.netbios_name.size;
4112 sid = &nrec->data.info.sid;
4116 if (!dns_name) continue;
4118 /* check if this is already taken and not excluded */
4119 for (i = 0; i < tdo_fti->count; i++) {
4120 trec = &tdo_fti->records[i].record;
4122 switch (trec->type) {
4123 case FOREST_TRUST_TOP_LEVEL_NAME:
4125 tname = trec->data.name.string;
4126 tlen = trec->data.name.size;
4128 case FOREST_TRUST_TOP_LEVEL_NAME_EX:
4130 tname = trec->data.name.string;
4131 tlen = trec->data.name.size;
4133 case FOREST_TRUST_DOMAIN_INFO:
4135 tname = trec->data.info.dns_name.string;
4136 tlen = trec->data.info.dns_name.size;
4138 ret = dns_cmp(dns_name, dns_len, tname, tlen);
4141 /* if it matches exclusion,
4142 * it doesn't conflict */
4148 case DNS_CMP_FIRST_IS_CHILD:
4149 case DNS_CMP_SECOND_IS_CHILD:
4150 tln_conflict = true;
4156 /* explicit exclusion, no dns name conflict here */
4158 tln_conflict = false;
4161 if (trec->type != FOREST_TRUST_DOMAIN_INFO) {
4165 /* also test for domain info */
4166 if (!(trec->flags & LSA_SID_DISABLED_ADMIN) &&
4167 dom_sid_compare(&trec->data.info.sid, sid) == 0) {
4168 sid_conflict = true;
4170 if (!(trec->flags & LSA_NB_DISABLED_ADMIN) &&
4171 strcasecmp_m(trec->data.info.netbios_name.string,
4178 nt_status = add_collision(c_info, new_fti_idx,
4180 LSA_TLN_DISABLED_CONFLICT,
4184 nt_status = add_collision(c_info, new_fti_idx,
4186 LSA_SID_DISABLED_CONFLICT,
4190 nt_status = add_collision(c_info, new_fti_idx,
4192 LSA_NB_DISABLED_CONFLICT,
4197 return NT_STATUS_OK;
4200 static NTSTATUS add_collision(struct lsa_ForestTrustCollisionInfo *c_info,
4201 uint32_t idx, uint32_t collision_type,
4202 uint32_t conflict_type, const char *tdo_name)
4204 struct lsa_ForestTrustCollisionRecord **es;
4205 uint32_t i = c_info->count;
4207 es = talloc_realloc(c_info, c_info->entries,
4208 struct lsa_ForestTrustCollisionRecord *, i + 1);
4210 return NT_STATUS_NO_MEMORY;
4212 c_info->entries = es;
4213 c_info->count = i + 1;
4215 es[i] = talloc(es, struct lsa_ForestTrustCollisionRecord);
4217 return NT_STATUS_NO_MEMORY;
4221 es[i]->type = collision_type;
4222 es[i]->flags.flags = conflict_type;
4223 es[i]->name.string = talloc_strdup(es[i], tdo_name);
4224 if (!es[i]->name.string) {
4225 return NT_STATUS_NO_MEMORY;
4227 es[i]->name.size = strlen(es[i]->name.string);
4229 return NT_STATUS_OK;
4233 lsa_lsaRSetForestTrustInformation
4235 static NTSTATUS dcesrv_lsa_lsaRSetForestTrustInformation(struct dcesrv_call_state *dce_call,
4236 TALLOC_CTX *mem_ctx,
4237 struct lsa_lsaRSetForestTrustInformation *r)
4239 struct dcesrv_handle *h;
4240 struct lsa_policy_state *p_state;
4241 const char *trust_attrs[] = { "trustPartner", "trustAttributes",
4242 "msDS-TrustForestTrustInfo", NULL };
4243 struct ldb_message **dom_res = NULL;
4244 struct ldb_dn *tdo_dn;
4245 struct ldb_message *msg;
4247 const char *td_name;
4248 uint32_t trust_attributes;
4249 struct lsa_ForestTrustCollisionInfo *c_info;
4250 struct ForestTrustInfo *nfti;
4251 struct ForestTrustInfo *fti;
4253 enum ndr_err_code ndr_err;
4258 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
4262 if (strcmp(p_state->domain_dns, p_state->forest_dns)) {
4263 return NT_STATUS_INVALID_DOMAIN_STATE;
4266 /* abort if we are not a PDC */
4267 if (!samdb_is_pdc(p_state->sam_ldb)) {
4268 return NT_STATUS_INVALID_DOMAIN_ROLE;
4271 ret = samdb_rodc(p_state->sam_ldb, &am_rodc);
4272 if (ret == LDB_SUCCESS && am_rodc) {
4273 return NT_STATUS_NO_SUCH_DOMAIN;
4276 /* check caller has TRUSTED_SET_AUTH */
4278 /* fetch all trusted domain objects */
4279 num_res = gendb_search(p_state->sam_ldb, mem_ctx,
4281 &dom_res, trust_attrs,
4282 "(objectclass=trustedDomain)");
4284 return NT_STATUS_NO_SUCH_DOMAIN;
4287 for (i = 0; i < num_res; i++) {
4288 td_name = ldb_msg_find_attr_as_string(dom_res[i],
4289 "trustPartner", NULL);
4291 return NT_STATUS_INVALID_DOMAIN_STATE;
4293 if (strcasecmp_m(td_name,
4294 r->in.trusted_domain_name->string) == 0) {
4299 return NT_STATUS_NO_SUCH_DOMAIN;
4302 tdo_dn = dom_res[i]->dn;
4304 trust_attributes = ldb_msg_find_attr_as_uint(dom_res[i],
4305 "trustAttributes", 0);
4306 if (!(trust_attributes & NETR_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
4307 return NT_STATUS_INVALID_PARAMETER;
4310 if (r->in.highest_record_type >= LSA_FOREST_TRUST_RECORD_TYPE_LAST) {
4311 return NT_STATUS_INVALID_PARAMETER;
4314 nfti = talloc(mem_ctx, struct ForestTrustInfo);
4316 return NT_STATUS_NO_MEMORY;
4319 nt_status = make_ft_info(nfti, r->in.forest_trust_info, nfti);
4320 if (!NT_STATUS_IS_OK(nt_status)) {
4324 c_info = talloc_zero(r->out.collision_info,
4325 struct lsa_ForestTrustCollisionInfo);
4327 return NT_STATUS_NO_MEMORY;
4330 /* first check own info, then other domains */
4331 fti = talloc(mem_ctx, struct ForestTrustInfo);
4333 return NT_STATUS_NO_MEMORY;
4336 nt_status = own_ft_info(p_state, fti);
4337 if (!NT_STATUS_IS_OK(nt_status)) {
4341 nt_status = check_ft_info(c_info, p_state->domain_dns,
4343 if (!NT_STATUS_IS_OK(nt_status)) {
4347 for (i = 0; i < num_res; i++) {
4348 fti = talloc(mem_ctx, struct ForestTrustInfo);
4350 return NT_STATUS_NO_MEMORY;
4353 nt_status = get_ft_info(mem_ctx, dom_res[i], fti);
4354 if (!NT_STATUS_IS_OK(nt_status)) {
4355 if (NT_STATUS_EQUAL(nt_status,
4356 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4362 td_name = ldb_msg_find_attr_as_string(dom_res[i],
4363 "trustPartner", NULL);
4365 return NT_STATUS_INVALID_DOMAIN_STATE;
4368 nt_status = check_ft_info(c_info, td_name, fti, nfti, c_info);
4369 if (!NT_STATUS_IS_OK(nt_status)) {
4374 *r->out.collision_info = c_info;
4376 if (r->in.check_only != 0) {
4377 return NT_STATUS_OK;
4380 /* not just a check, write info back */
4382 ndr_err = ndr_push_struct_blob(&ft_blob, mem_ctx, nfti,
4383 (ndr_push_flags_fn_t)ndr_push_ForestTrustInfo);
4384 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
4385 return NT_STATUS_INVALID_PARAMETER;
4388 msg = ldb_msg_new(mem_ctx);
4390 return NT_STATUS_NO_MEMORY;
4393 msg->dn = ldb_dn_copy(mem_ctx, tdo_dn);
4395 return NT_STATUS_NO_MEMORY;
4398 ret = ldb_msg_add_empty(msg, "msDS-TrustForestTrustInfo",
4399 LDB_FLAG_MOD_REPLACE, NULL);
4400 if (ret != LDB_SUCCESS) {
4401 return NT_STATUS_NO_MEMORY;
4403 ret = ldb_msg_add_value(msg, "msDS-TrustForestTrustInfo",
4405 if (ret != LDB_SUCCESS) {
4406 return NT_STATUS_NO_MEMORY;
4409 ret = ldb_modify(p_state->sam_ldb, msg);
4410 if (ret != LDB_SUCCESS) {
4411 DEBUG(0, ("Failed to store Forest Trust Info: %s\n",
4412 ldb_errstring(p_state->sam_ldb)));
4415 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
4416 return NT_STATUS_ACCESS_DENIED;
4418 return NT_STATUS_INTERNAL_DB_CORRUPTION;
4422 return NT_STATUS_OK;
4428 static NTSTATUS dcesrv_lsa_CREDRRENAME(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4429 struct lsa_CREDRRENAME *r)
4431 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4437 lsa_LSAROPENPOLICYSCE
4439 static NTSTATUS dcesrv_lsa_LSAROPENPOLICYSCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4440 struct lsa_LSAROPENPOLICYSCE *r)
4442 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4447 lsa_LSARADTREGISTERSECURITYEVENTSOURCE
4449 static NTSTATUS dcesrv_lsa_LSARADTREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4450 struct lsa_LSARADTREGISTERSECURITYEVENTSOURCE *r)
4452 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4457 lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE
4459 static NTSTATUS dcesrv_lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4460 struct lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE *r)
4462 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4467 lsa_LSARADTREPORTSECURITYEVENT
4469 static NTSTATUS dcesrv_lsa_LSARADTREPORTSECURITYEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4470 struct lsa_LSARADTREPORTSECURITYEVENT *r)
4472 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4476 /* include the generated boilerplate */
4477 #include "librpc/gen_ndr/ndr_lsa_s.c"
4481 /*****************************************
4482 NOTE! The remaining calls below were
4483 removed in w2k3, so the DCESRV_FAULT()
4484 replies are the correct implementation. Do
4485 not try and fill these in with anything else
4486 ******************************************/
4489 dssetup_DsRoleDnsNameToFlatName
4491 static WERROR dcesrv_dssetup_DsRoleDnsNameToFlatName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4492 struct dssetup_DsRoleDnsNameToFlatName *r)
4494 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4499 dssetup_DsRoleDcAsDc
4501 static WERROR dcesrv_dssetup_DsRoleDcAsDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4502 struct dssetup_DsRoleDcAsDc *r)
4504 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4509 dssetup_DsRoleDcAsReplica
4511 static WERROR dcesrv_dssetup_DsRoleDcAsReplica(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4512 struct dssetup_DsRoleDcAsReplica *r)
4514 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4519 dssetup_DsRoleDemoteDc
4521 static WERROR dcesrv_dssetup_DsRoleDemoteDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4522 struct dssetup_DsRoleDemoteDc *r)
4524 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4529 dssetup_DsRoleGetDcOperationProgress
4531 static WERROR dcesrv_dssetup_DsRoleGetDcOperationProgress(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4532 struct dssetup_DsRoleGetDcOperationProgress *r)
4534 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4539 dssetup_DsRoleGetDcOperationResults
4541 static WERROR dcesrv_dssetup_DsRoleGetDcOperationResults(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4542 struct dssetup_DsRoleGetDcOperationResults *r)
4544 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4549 dssetup_DsRoleCancel
4551 static WERROR dcesrv_dssetup_DsRoleCancel(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4552 struct dssetup_DsRoleCancel *r)
4554 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4559 dssetup_DsRoleServerSaveStateForUpgrade
4561 static WERROR dcesrv_dssetup_DsRoleServerSaveStateForUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4562 struct dssetup_DsRoleServerSaveStateForUpgrade *r)
4564 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4569 dssetup_DsRoleUpgradeDownlevelServer
4571 static WERROR dcesrv_dssetup_DsRoleUpgradeDownlevelServer(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4572 struct dssetup_DsRoleUpgradeDownlevelServer *r)
4574 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4579 dssetup_DsRoleAbortDownlevelServerUpgrade
4581 static WERROR dcesrv_dssetup_DsRoleAbortDownlevelServerUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4582 struct dssetup_DsRoleAbortDownlevelServerUpgrade *r)
4584 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4588 /* include the generated boilerplate */
4589 #include "librpc/gen_ndr/ndr_dssetup_s.c"
4591 NTSTATUS dcerpc_server_lsa_init(void)
4595 ret = dcerpc_server_dssetup_init();
4596 if (!NT_STATUS_IS_OK(ret)) {
4599 ret = dcerpc_server_lsarpc_init();
4600 if (!NT_STATUS_IS_OK(ret)) {