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"
36 this type allows us to distinguish handle types
40 state associated with a lsa_OpenAccount() operation
42 struct lsa_account_state {
43 struct lsa_policy_state *policy;
45 struct dom_sid *account_sid;
50 state associated with a lsa_OpenSecret() operation
52 struct lsa_secret_state {
53 struct lsa_policy_state *policy;
55 struct ldb_dn *secret_dn;
56 struct ldb_context *sam_ldb;
61 state associated with a lsa_OpenTrustedDomain() operation
63 struct lsa_trusted_domain_state {
64 struct lsa_policy_state *policy;
66 struct ldb_dn *trusted_domain_dn;
67 struct ldb_dn *trusted_domain_user_dn;
71 this is based on the samba3 function make_lsa_object_sd()
72 It uses the same logic, but with samba4 helper functions
74 static NTSTATUS dcesrv_build_lsa_sd(TALLOC_CTX *mem_ctx,
75 struct security_descriptor **sd,
81 struct dom_sid *domain_sid, *domain_admins_sid;
82 const char *domain_admins_sid_str, *sidstr;
83 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
85 status = dom_sid_split_rid(tmp_ctx, sid, &domain_sid, &rid);
86 NT_STATUS_NOT_OK_RETURN_AND_FREE(status, tmp_ctx);
88 domain_admins_sid = dom_sid_add_rid(tmp_ctx, domain_sid, DOMAIN_RID_ADMINS);
89 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(domain_admins_sid, tmp_ctx);
91 domain_admins_sid_str = dom_sid_string(tmp_ctx, domain_admins_sid);
92 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(domain_admins_sid_str, tmp_ctx);
94 sidstr = dom_sid_string(tmp_ctx, sid);
95 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sidstr, tmp_ctx);
97 *sd = security_descriptor_dacl_create(mem_ctx,
101 SEC_ACE_TYPE_ACCESS_ALLOWED,
102 SEC_GENERIC_EXECUTE | SEC_GENERIC_READ, 0,
104 SID_BUILTIN_ADMINISTRATORS,
105 SEC_ACE_TYPE_ACCESS_ALLOWED,
108 SID_BUILTIN_ACCOUNT_OPERATORS,
109 SEC_ACE_TYPE_ACCESS_ALLOWED,
112 domain_admins_sid_str,
113 SEC_ACE_TYPE_ACCESS_ALLOWED,
117 SEC_ACE_TYPE_ACCESS_ALLOWED,
121 talloc_free(tmp_ctx);
123 NT_STATUS_HAVE_NO_MEMORY(*sd);
129 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call,
131 struct lsa_EnumAccountRights *r);
133 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
135 struct lsa_policy_state *state,
138 const struct lsa_RightSet *rights);
143 static NTSTATUS dcesrv_lsa_Close(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
146 struct dcesrv_handle *h;
148 *r->out.handle = *r->in.handle;
150 DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
154 ZERO_STRUCTP(r->out.handle);
163 static NTSTATUS dcesrv_lsa_Delete(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
164 struct lsa_Delete *r)
166 return NT_STATUS_NOT_SUPPORTED;
173 static NTSTATUS dcesrv_lsa_DeleteObject(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
174 struct lsa_DeleteObject *r)
176 struct dcesrv_handle *h;
179 DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
181 if (h->wire_handle.handle_type == LSA_HANDLE_SECRET) {
182 struct lsa_secret_state *secret_state = h->data;
184 /* Ensure user is permitted to delete this... */
185 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
187 case SECURITY_SYSTEM:
188 case SECURITY_ADMINISTRATOR:
191 /* Users and anonymous are not allowed to delete things */
192 return NT_STATUS_ACCESS_DENIED;
195 ret = ldb_delete(secret_state->sam_ldb,
196 secret_state->secret_dn);
197 if (ret != LDB_SUCCESS) {
198 return NT_STATUS_INVALID_HANDLE;
201 ZERO_STRUCTP(r->out.handle);
205 } else if (h->wire_handle.handle_type == LSA_HANDLE_TRUSTED_DOMAIN) {
206 struct lsa_trusted_domain_state *trusted_domain_state =
207 talloc_get_type(h->data, struct lsa_trusted_domain_state);
208 ret = ldb_transaction_start(trusted_domain_state->policy->sam_ldb);
209 if (ret != LDB_SUCCESS) {
210 return NT_STATUS_INTERNAL_DB_CORRUPTION;
213 ret = ldb_delete(trusted_domain_state->policy->sam_ldb,
214 trusted_domain_state->trusted_domain_dn);
215 if (ret != LDB_SUCCESS) {
216 ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
217 return NT_STATUS_INVALID_HANDLE;
220 if (trusted_domain_state->trusted_domain_user_dn) {
221 ret = ldb_delete(trusted_domain_state->policy->sam_ldb,
222 trusted_domain_state->trusted_domain_user_dn);
223 if (ret != LDB_SUCCESS) {
224 ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
225 return NT_STATUS_INVALID_HANDLE;
229 ret = ldb_transaction_commit(trusted_domain_state->policy->sam_ldb);
230 if (ret != LDB_SUCCESS) {
231 return NT_STATUS_INTERNAL_DB_CORRUPTION;
234 ZERO_STRUCTP(r->out.handle);
238 } else if (h->wire_handle.handle_type == LSA_HANDLE_ACCOUNT) {
239 struct lsa_RightSet *rights;
240 struct lsa_account_state *astate;
241 struct lsa_EnumAccountRights r2;
244 rights = talloc(mem_ctx, struct lsa_RightSet);
246 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
250 r2.in.handle = &astate->policy->handle->wire_handle;
251 r2.in.sid = astate->account_sid;
252 r2.out.rights = rights;
254 /* dcesrv_lsa_EnumAccountRights takes a LSA_HANDLE_POLICY,
255 but we have a LSA_HANDLE_ACCOUNT here, so this call
257 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
258 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
262 if (!NT_STATUS_IS_OK(status)) {
266 status = dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
267 LDB_FLAG_MOD_DELETE, astate->account_sid,
269 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
273 if (!NT_STATUS_IS_OK(status)) {
277 ZERO_STRUCTP(r->out.handle);
282 return NT_STATUS_INVALID_HANDLE;
289 static NTSTATUS dcesrv_lsa_EnumPrivs(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
290 struct lsa_EnumPrivs *r)
292 struct dcesrv_handle *h;
293 struct lsa_policy_state *state;
295 enum sec_privilege priv;
296 const char *privname;
298 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
302 i = *r->in.resume_handle;
304 while (((priv = sec_privilege_from_index(i)) != SEC_PRIV_INVALID) &&
305 r->out.privs->count < r->in.max_count) {
306 struct lsa_PrivEntry *e;
307 privname = sec_privilege_name(priv);
308 r->out.privs->privs = talloc_realloc(r->out.privs,
310 struct lsa_PrivEntry,
311 r->out.privs->count+1);
312 if (r->out.privs->privs == NULL) {
313 return NT_STATUS_NO_MEMORY;
315 e = &r->out.privs->privs[r->out.privs->count];
318 e->name.string = privname;
319 r->out.privs->count++;
323 *r->out.resume_handle = i;
332 static NTSTATUS dcesrv_lsa_QuerySecurity(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
333 struct lsa_QuerySecurity *r)
335 struct dcesrv_handle *h;
336 struct security_descriptor *sd;
340 DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
342 sid = &dce_call->conn->auth_state.session_info->security_token->sids[PRIMARY_USER_SID_INDEX];
344 if (h->wire_handle.handle_type == LSA_HANDLE_POLICY) {
345 status = dcesrv_build_lsa_sd(mem_ctx, &sd, sid, 0);
346 } else if (h->wire_handle.handle_type == LSA_HANDLE_ACCOUNT) {
347 status = dcesrv_build_lsa_sd(mem_ctx, &sd, sid,
348 LSA_ACCOUNT_ALL_ACCESS);
350 return NT_STATUS_INVALID_HANDLE;
352 NT_STATUS_NOT_OK_RETURN(status);
354 (*r->out.sdbuf) = talloc(mem_ctx, struct sec_desc_buf);
355 NT_STATUS_HAVE_NO_MEMORY(*r->out.sdbuf);
357 (*r->out.sdbuf)->sd = sd;
366 static NTSTATUS dcesrv_lsa_SetSecObj(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
367 struct lsa_SetSecObj *r)
369 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
376 static NTSTATUS dcesrv_lsa_ChangePassword(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
377 struct lsa_ChangePassword *r)
379 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
383 dssetup_DsRoleGetPrimaryDomainInformation
385 This is not an LSA call, but is the only call left on the DSSETUP
386 pipe (after the pipe was truncated), and needs lsa_get_policy_state
388 static WERROR dcesrv_dssetup_DsRoleGetPrimaryDomainInformation(struct dcesrv_call_state *dce_call,
390 struct dssetup_DsRoleGetPrimaryDomainInformation *r)
392 union dssetup_DsRoleInfo *info;
394 info = talloc_zero(mem_ctx, union dssetup_DsRoleInfo);
395 W_ERROR_HAVE_NO_MEMORY(info);
397 switch (r->in.level) {
398 case DS_ROLE_BASIC_INFORMATION:
400 enum dssetup_DsRole role = DS_ROLE_STANDALONE_SERVER;
402 const char *domain = NULL;
403 const char *dns_domain = NULL;
404 const char *forest = NULL;
405 struct GUID domain_guid;
406 struct lsa_policy_state *state;
408 NTSTATUS status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx, &state);
409 if (!NT_STATUS_IS_OK(status)) {
410 return ntstatus_to_werror(status);
413 ZERO_STRUCT(domain_guid);
415 switch (lpcfg_server_role(dce_call->conn->dce_ctx->lp_ctx)) {
416 case ROLE_STANDALONE:
417 role = DS_ROLE_STANDALONE_SERVER;
419 case ROLE_DOMAIN_MEMBER:
420 role = DS_ROLE_MEMBER_SERVER;
422 case ROLE_DOMAIN_CONTROLLER:
423 if (samdb_is_pdc(state->sam_ldb)) {
424 role = DS_ROLE_PRIMARY_DC;
426 role = DS_ROLE_BACKUP_DC;
431 switch (lpcfg_server_role(dce_call->conn->dce_ctx->lp_ctx)) {
432 case ROLE_STANDALONE:
433 domain = talloc_strdup(mem_ctx, lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx));
434 W_ERROR_HAVE_NO_MEMORY(domain);
436 case ROLE_DOMAIN_MEMBER:
437 domain = talloc_strdup(mem_ctx, lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx));
438 W_ERROR_HAVE_NO_MEMORY(domain);
439 /* TODO: what is with dns_domain and forest and guid? */
441 case ROLE_DOMAIN_CONTROLLER:
442 flags = DS_ROLE_PRIMARY_DS_RUNNING;
444 if (state->mixed_domain == 1) {
445 flags |= DS_ROLE_PRIMARY_DS_MIXED_MODE;
448 domain = state->domain_name;
449 dns_domain = state->domain_dns;
450 forest = state->forest_dns;
452 domain_guid = state->domain_guid;
453 flags |= DS_ROLE_PRIMARY_DOMAIN_GUID_PRESENT;
457 info->basic.role = role;
458 info->basic.flags = flags;
459 info->basic.domain = domain;
460 info->basic.dns_domain = dns_domain;
461 info->basic.forest = forest;
462 info->basic.domain_guid = domain_guid;
467 case DS_ROLE_UPGRADE_STATUS:
469 info->upgrade.upgrading = DS_ROLE_NOT_UPGRADING;
470 info->upgrade.previous_role = DS_ROLE_PREVIOUS_UNKNOWN;
475 case DS_ROLE_OP_STATUS:
477 info->opstatus.status = DS_ROLE_OP_IDLE;
483 return WERR_INVALID_PARAM;
488 fill in the AccountDomain info
490 static NTSTATUS dcesrv_lsa_info_AccountDomain(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
491 struct lsa_DomainInfo *info)
493 info->name.string = state->domain_name;
494 info->sid = state->domain_sid;
500 fill in the DNS domain info
502 static NTSTATUS dcesrv_lsa_info_DNS(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
503 struct lsa_DnsDomainInfo *info)
505 info->name.string = state->domain_name;
506 info->sid = state->domain_sid;
507 info->dns_domain.string = state->domain_dns;
508 info->dns_forest.string = state->forest_dns;
509 info->domain_guid = state->domain_guid;
517 static NTSTATUS dcesrv_lsa_QueryInfoPolicy2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
518 struct lsa_QueryInfoPolicy2 *r)
520 struct lsa_policy_state *state;
521 struct dcesrv_handle *h;
522 union lsa_PolicyInformation *info;
526 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
530 info = talloc_zero(mem_ctx, union lsa_PolicyInformation);
532 return NT_STATUS_NO_MEMORY;
536 switch (r->in.level) {
537 case LSA_POLICY_INFO_AUDIT_LOG:
538 /* we don't need to fill in any of this */
539 ZERO_STRUCT(info->audit_log);
541 case LSA_POLICY_INFO_AUDIT_EVENTS:
542 /* we don't need to fill in any of this */
543 ZERO_STRUCT(info->audit_events);
545 case LSA_POLICY_INFO_PD:
546 /* we don't need to fill in any of this */
547 ZERO_STRUCT(info->pd);
550 case LSA_POLICY_INFO_DOMAIN:
551 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->domain);
552 case LSA_POLICY_INFO_ACCOUNT_DOMAIN:
553 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->account_domain);
554 case LSA_POLICY_INFO_L_ACCOUNT_DOMAIN:
555 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->l_account_domain);
557 case LSA_POLICY_INFO_ROLE:
558 info->role.role = LSA_ROLE_PRIMARY;
561 case LSA_POLICY_INFO_DNS:
562 case LSA_POLICY_INFO_DNS_INT:
563 return dcesrv_lsa_info_DNS(state, mem_ctx, &info->dns);
565 case LSA_POLICY_INFO_REPLICA:
566 ZERO_STRUCT(info->replica);
569 case LSA_POLICY_INFO_QUOTA:
570 ZERO_STRUCT(info->quota);
573 case LSA_POLICY_INFO_MOD:
574 case LSA_POLICY_INFO_AUDIT_FULL_SET:
575 case LSA_POLICY_INFO_AUDIT_FULL_QUERY:
576 /* windows gives INVALID_PARAMETER */
578 return NT_STATUS_INVALID_PARAMETER;
582 return NT_STATUS_INVALID_INFO_CLASS;
588 static NTSTATUS dcesrv_lsa_QueryInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
589 struct lsa_QueryInfoPolicy *r)
591 struct lsa_QueryInfoPolicy2 r2;
596 r2.in.handle = r->in.handle;
597 r2.in.level = r->in.level;
598 r2.out.info = r->out.info;
600 status = dcesrv_lsa_QueryInfoPolicy2(dce_call, mem_ctx, &r2);
608 static NTSTATUS dcesrv_lsa_SetInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
609 struct lsa_SetInfoPolicy *r)
611 /* need to support this */
612 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
619 static NTSTATUS dcesrv_lsa_ClearAuditLog(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
620 struct lsa_ClearAuditLog *r)
622 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
629 This call does not seem to have any long-term effects, hence no database operations
631 we need to talk to the MS product group to find out what this account database means!
633 answer is that the lsa database is totally separate from the SAM and
634 ldap databases. We are going to need a separate ldb to store these
635 accounts. The SIDs on this account bear no relation to the SIDs in
638 static NTSTATUS dcesrv_lsa_CreateAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
639 struct lsa_CreateAccount *r)
641 struct lsa_account_state *astate;
643 struct lsa_policy_state *state;
644 struct dcesrv_handle *h, *ah;
646 ZERO_STRUCTP(r->out.acct_handle);
648 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
652 astate = talloc(dce_call->conn, struct lsa_account_state);
653 if (astate == NULL) {
654 return NT_STATUS_NO_MEMORY;
657 astate->account_sid = dom_sid_dup(astate, r->in.sid);
658 if (astate->account_sid == NULL) {
660 return NT_STATUS_NO_MEMORY;
663 astate->policy = talloc_reference(astate, state);
664 astate->access_mask = r->in.access_mask;
666 ah = dcesrv_handle_new(dce_call->context, LSA_HANDLE_ACCOUNT);
669 return NT_STATUS_NO_MEMORY;
672 ah->data = talloc_steal(ah, astate);
674 *r->out.acct_handle = ah->wire_handle;
683 static NTSTATUS dcesrv_lsa_EnumAccounts(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
684 struct lsa_EnumAccounts *r)
686 struct dcesrv_handle *h;
687 struct lsa_policy_state *state;
689 struct ldb_message **res;
690 const char * const attrs[] = { "objectSid", NULL};
693 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
697 /* NOTE: This call must only return accounts that have at least
700 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
701 "(&(objectSid=*)(privilege=*))");
703 return NT_STATUS_INTERNAL_DB_CORRUPTION;
706 if (*r->in.resume_handle >= ret) {
707 return NT_STATUS_NO_MORE_ENTRIES;
710 count = ret - *r->in.resume_handle;
711 if (count > r->in.num_entries) {
712 count = r->in.num_entries;
716 return NT_STATUS_NO_MORE_ENTRIES;
719 r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, count);
720 if (r->out.sids->sids == NULL) {
721 return NT_STATUS_NO_MEMORY;
724 for (i=0;i<count;i++) {
725 r->out.sids->sids[i].sid =
726 samdb_result_dom_sid(r->out.sids->sids,
727 res[i + *r->in.resume_handle],
729 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
732 r->out.sids->num_sids = count;
733 *r->out.resume_handle = count + *r->in.resume_handle;
739 /* This decrypts and returns Trusted Domain Auth Information Internal data */
740 static NTSTATUS get_trustdom_auth_blob(struct dcesrv_call_state *dce_call,
741 TALLOC_CTX *mem_ctx, DATA_BLOB *auth_blob,
742 struct trustDomainPasswords *auth_struct)
744 DATA_BLOB session_key = data_blob(NULL, 0);
745 enum ndr_err_code ndr_err;
748 nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
749 if (!NT_STATUS_IS_OK(nt_status)) {
753 arcfour_crypt_blob(auth_blob->data, auth_blob->length, &session_key);
754 ndr_err = ndr_pull_struct_blob(auth_blob, mem_ctx,
756 (ndr_pull_flags_fn_t)ndr_pull_trustDomainPasswords);
757 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
758 return NT_STATUS_INVALID_PARAMETER;
764 static NTSTATUS get_trustauth_inout_blob(struct dcesrv_call_state *dce_call,
766 struct trustAuthInOutBlob *iopw,
767 DATA_BLOB *trustauth_blob)
769 enum ndr_err_code ndr_err;
771 ndr_err = ndr_push_struct_blob(trustauth_blob, mem_ctx,
773 (ndr_push_flags_fn_t)ndr_push_trustAuthInOutBlob);
774 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
775 return NT_STATUS_INVALID_PARAMETER;
781 static NTSTATUS add_trust_user(TALLOC_CTX *mem_ctx,
782 struct ldb_context *sam_ldb,
783 struct ldb_dn *base_dn,
784 const char *netbios_name,
785 struct trustAuthInOutBlob *in,
786 struct ldb_dn **user_dn)
788 struct ldb_message *msg;
793 dn = ldb_dn_copy(mem_ctx, base_dn);
795 return NT_STATUS_NO_MEMORY;
797 if (!ldb_dn_add_child_fmt(dn, "cn=%s$,cn=users", netbios_name)) {
798 return NT_STATUS_NO_MEMORY;
801 msg = ldb_msg_new(mem_ctx);
803 return NT_STATUS_NO_MEMORY;
807 ret = ldb_msg_add_string(msg, "objectClass", "user");
808 if (ret != LDB_SUCCESS) {
809 return NT_STATUS_NO_MEMORY;
812 ret = ldb_msg_add_fmt(msg, "samAccountName", "%s$", netbios_name);
813 if (ret != LDB_SUCCESS) {
814 return NT_STATUS_NO_MEMORY;
817 ret = samdb_msg_add_uint(sam_ldb, msg, msg, "userAccountControl",
818 UF_INTERDOMAIN_TRUST_ACCOUNT);
819 if (ret != LDB_SUCCESS) {
820 return NT_STATUS_NO_MEMORY;
823 for (i = 0; i < in->count; i++) {
824 const char *attribute;
826 switch (in->current.array[i].AuthType) {
827 case TRUST_AUTH_TYPE_NT4OWF:
828 attribute = "unicodePwd";
829 v.data = (uint8_t *)&in->current.array[i].AuthInfo.nt4owf.password;
832 case TRUST_AUTH_TYPE_CLEAR:
833 attribute = "clearTextPassword";
834 v.data = in->current.array[i].AuthInfo.clear.password;
835 v.length = in->current.array[i].AuthInfo.clear.size;
841 ret = ldb_msg_add_value(msg, attribute, &v, NULL);
842 if (ret != LDB_SUCCESS) {
843 return NT_STATUS_NO_MEMORY;
847 /* create the trusted_domain user account */
848 ret = ldb_add(sam_ldb, msg);
849 if (ret != LDB_SUCCESS) {
850 DEBUG(0,("Failed to create user record %s: %s\n",
851 ldb_dn_get_linearized(msg->dn),
852 ldb_errstring(sam_ldb)));
855 case LDB_ERR_ENTRY_ALREADY_EXISTS:
856 return NT_STATUS_DOMAIN_EXISTS;
857 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
858 return NT_STATUS_ACCESS_DENIED;
860 return NT_STATUS_INTERNAL_DB_CORRUPTION;
871 lsa_CreateTrustedDomainEx2
873 static NTSTATUS dcesrv_lsa_CreateTrustedDomain_base(struct dcesrv_call_state *dce_call,
875 struct lsa_CreateTrustedDomainEx2 *r,
878 struct dcesrv_handle *policy_handle;
879 struct lsa_policy_state *policy_state;
880 struct lsa_trusted_domain_state *trusted_domain_state;
881 struct dcesrv_handle *handle;
882 struct ldb_message **msgs, *msg;
883 const char *attrs[] = {
886 const char *netbios_name;
887 const char *dns_name;
889 DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
890 struct trustDomainPasswords auth_struct;
893 struct ldb_context *sam_ldb;
895 DCESRV_PULL_HANDLE(policy_handle, r->in.policy_handle, LSA_HANDLE_POLICY);
896 ZERO_STRUCTP(r->out.trustdom_handle);
898 policy_state = policy_handle->data;
899 sam_ldb = policy_state->sam_ldb;
901 netbios_name = r->in.info->netbios_name.string;
903 return NT_STATUS_INVALID_PARAMETER;
906 dns_name = r->in.info->domain_name.string;
908 trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
909 if (!trusted_domain_state) {
910 return NT_STATUS_NO_MEMORY;
912 trusted_domain_state->policy = policy_state;
914 if (strcasecmp(netbios_name, "BUILTIN") == 0
915 || (dns_name && strcasecmp(dns_name, "BUILTIN") == 0)
916 || (dom_sid_in_domain(policy_state->builtin_sid, r->in.info->sid))) {
917 return NT_STATUS_INVALID_PARAMETER;
920 if (strcasecmp(netbios_name, policy_state->domain_name) == 0
921 || strcasecmp(netbios_name, policy_state->domain_dns) == 0
922 || (dns_name && strcasecmp(dns_name, policy_state->domain_dns) == 0)
923 || (dns_name && strcasecmp(dns_name, policy_state->domain_name) == 0)
924 || (dom_sid_equal(policy_state->domain_sid, r->in.info->sid))) {
925 return NT_STATUS_CURRENT_DOMAIN_NOT_ALLOWED;
928 /* While this is a REF pointer, some of the functions that wrap this don't provide this */
929 if (op == NDR_LSA_CREATETRUSTEDDOMAIN) {
930 /* No secrets are created at this time, for this function */
931 auth_struct.outgoing.count = 0;
932 auth_struct.incoming.count = 0;
934 auth_blob = data_blob_const(r->in.auth_info->auth_blob.data,
935 r->in.auth_info->auth_blob.size);
936 nt_status = get_trustdom_auth_blob(dce_call, mem_ctx,
937 &auth_blob, &auth_struct);
938 if (!NT_STATUS_IS_OK(nt_status)) {
942 if (op == NDR_LSA_CREATETRUSTEDDOMAINEX) {
943 if (auth_struct.incoming.count > 1) {
944 return NT_STATUS_INVALID_PARAMETER;
949 if (auth_struct.incoming.count) {
950 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
951 &auth_struct.incoming,
953 if (!NT_STATUS_IS_OK(nt_status)) {
957 trustAuthIncoming = data_blob(NULL, 0);
960 if (auth_struct.outgoing.count) {
961 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
962 &auth_struct.outgoing,
964 if (!NT_STATUS_IS_OK(nt_status)) {
968 trustAuthOutgoing = data_blob(NULL, 0);
971 ret = ldb_transaction_start(sam_ldb);
972 if (ret != LDB_SUCCESS) {
973 return NT_STATUS_INTERNAL_DB_CORRUPTION;
977 char *dns_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
978 char *netbios_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
979 /* search for the trusted_domain record */
980 ret = gendb_search(sam_ldb,
981 mem_ctx, policy_state->system_dn, &msgs, attrs,
982 "(&(|(flatname=%s)(cn=%s)(trustPartner=%s)(flatname=%s)(cn=%s)(trustPartner=%s))(objectclass=trustedDomain))",
983 dns_encoded, dns_encoded, dns_encoded, netbios_encoded, netbios_encoded, netbios_encoded);
985 ldb_transaction_cancel(sam_ldb);
986 return NT_STATUS_OBJECT_NAME_COLLISION;
989 char *netbios_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
990 /* search for the trusted_domain record */
991 ret = gendb_search(sam_ldb,
992 mem_ctx, policy_state->system_dn, &msgs, attrs,
993 "(&(|(flatname=%s)(cn=%s)(trustPartner=%s))(objectclass=trustedDomain))",
994 netbios_encoded, netbios_encoded, netbios_encoded);
996 ldb_transaction_cancel(sam_ldb);
997 return NT_STATUS_OBJECT_NAME_COLLISION;
1002 ldb_transaction_cancel(sam_ldb);
1003 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1006 name = dns_name ? dns_name : netbios_name;
1008 msg = ldb_msg_new(mem_ctx);
1010 return NT_STATUS_NO_MEMORY;
1013 msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
1014 if ( ! ldb_dn_add_child_fmt(msg->dn, "cn=%s", name)) {
1015 ldb_transaction_cancel(sam_ldb);
1016 return NT_STATUS_NO_MEMORY;
1019 samdb_msg_add_string(sam_ldb, mem_ctx, msg, "flatname", netbios_name);
1021 if (r->in.info->sid) {
1022 ret = samdb_msg_add_dom_sid(sam_ldb, mem_ctx, msg, "securityIdentifier", r->in.info->sid);
1023 if (ret != LDB_SUCCESS) {
1024 ldb_transaction_cancel(sam_ldb);
1025 return NT_STATUS_INVALID_PARAMETER;
1029 samdb_msg_add_string(sam_ldb, mem_ctx, msg, "objectClass", "trustedDomain");
1031 samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustType", r->in.info->trust_type);
1033 samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustAttributes", r->in.info->trust_attributes);
1035 samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustDirection", r->in.info->trust_direction);
1038 samdb_msg_add_string(sam_ldb, mem_ctx, msg, "trustPartner", dns_name);
1041 if (trustAuthIncoming.data) {
1042 ret = ldb_msg_add_value(msg, "trustAuthIncoming", &trustAuthIncoming, NULL);
1043 if (ret != LDB_SUCCESS) {
1044 ldb_transaction_cancel(sam_ldb);
1045 return NT_STATUS_NO_MEMORY;
1048 if (trustAuthOutgoing.data) {
1049 ret = ldb_msg_add_value(msg, "trustAuthOutgoing", &trustAuthOutgoing, NULL);
1050 if (ret != LDB_SUCCESS) {
1051 ldb_transaction_cancel(sam_ldb);
1052 return NT_STATUS_NO_MEMORY;
1056 trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msg->dn);
1058 /* create the trusted_domain */
1059 ret = ldb_add(sam_ldb, msg);
1063 case LDB_ERR_ENTRY_ALREADY_EXISTS:
1064 ldb_transaction_cancel(sam_ldb);
1065 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1066 ldb_dn_get_linearized(msg->dn),
1067 ldb_errstring(sam_ldb)));
1068 return NT_STATUS_DOMAIN_EXISTS;
1069 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1070 ldb_transaction_cancel(sam_ldb);
1071 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1072 ldb_dn_get_linearized(msg->dn),
1073 ldb_errstring(sam_ldb)));
1074 return NT_STATUS_ACCESS_DENIED;
1076 ldb_transaction_cancel(sam_ldb);
1077 DEBUG(0,("Failed to create user record %s: %s\n",
1078 ldb_dn_get_linearized(msg->dn),
1079 ldb_errstring(sam_ldb)));
1080 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1083 if (r->in.info->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
1084 struct ldb_dn *user_dn;
1085 /* Inbound trusts must also create a cn=users object to match */
1086 nt_status = add_trust_user(mem_ctx, sam_ldb,
1087 policy_state->domain_dn,
1089 &auth_struct.incoming,
1091 if (!NT_STATUS_IS_OK(nt_status)) {
1092 ldb_transaction_cancel(sam_ldb);
1096 /* save the trust user dn */
1097 trusted_domain_state->trusted_domain_user_dn
1098 = talloc_steal(trusted_domain_state, user_dn);
1101 ret = ldb_transaction_commit(sam_ldb);
1102 if (ret != LDB_SUCCESS) {
1103 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1106 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1108 return NT_STATUS_NO_MEMORY;
1111 handle->data = talloc_steal(handle, trusted_domain_state);
1113 trusted_domain_state->access_mask = r->in.access_mask;
1114 trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
1116 *r->out.trustdom_handle = handle->wire_handle;
1118 return NT_STATUS_OK;
1122 lsa_CreateTrustedDomainEx2
1124 static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx2(struct dcesrv_call_state *dce_call,
1125 TALLOC_CTX *mem_ctx,
1126 struct lsa_CreateTrustedDomainEx2 *r)
1128 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, r, NDR_LSA_CREATETRUSTEDDOMAINEX2);
1131 lsa_CreateTrustedDomainEx
1133 static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx(struct dcesrv_call_state *dce_call,
1134 TALLOC_CTX *mem_ctx,
1135 struct lsa_CreateTrustedDomainEx *r)
1137 struct lsa_CreateTrustedDomainEx2 r2;
1139 r2.in.policy_handle = r->in.policy_handle;
1140 r2.in.info = r->in.info;
1141 r2.in.auth_info = r->in.auth_info;
1142 r2.out.trustdom_handle = r->out.trustdom_handle;
1143 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAINEX);
1147 lsa_CreateTrustedDomain
1149 static NTSTATUS dcesrv_lsa_CreateTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1150 struct lsa_CreateTrustedDomain *r)
1152 struct lsa_CreateTrustedDomainEx2 r2;
1154 r2.in.policy_handle = r->in.policy_handle;
1155 r2.in.info = talloc(mem_ctx, struct lsa_TrustDomainInfoInfoEx);
1157 return NT_STATUS_NO_MEMORY;
1160 r2.in.info->domain_name.string = NULL;
1161 r2.in.info->netbios_name = r->in.info->name;
1162 r2.in.info->sid = r->in.info->sid;
1163 r2.in.info->trust_direction = LSA_TRUST_DIRECTION_OUTBOUND;
1164 r2.in.info->trust_type = LSA_TRUST_TYPE_DOWNLEVEL;
1165 r2.in.info->trust_attributes = 0;
1167 r2.in.access_mask = r->in.access_mask;
1168 r2.out.trustdom_handle = r->out.trustdom_handle;
1170 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAIN);
1175 lsa_OpenTrustedDomain
1177 static NTSTATUS dcesrv_lsa_OpenTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1178 struct lsa_OpenTrustedDomain *r)
1180 struct dcesrv_handle *policy_handle;
1182 struct lsa_policy_state *policy_state;
1183 struct lsa_trusted_domain_state *trusted_domain_state;
1184 struct dcesrv_handle *handle;
1185 struct ldb_message **msgs;
1186 const char *attrs[] = {
1192 const char *sid_string;
1195 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1196 ZERO_STRUCTP(r->out.trustdom_handle);
1197 policy_state = policy_handle->data;
1199 trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
1200 if (!trusted_domain_state) {
1201 return NT_STATUS_NO_MEMORY;
1203 trusted_domain_state->policy = policy_state;
1205 sid_string = dom_sid_string(mem_ctx, r->in.sid);
1207 return NT_STATUS_NO_MEMORY;
1210 /* search for the trusted_domain record */
1211 ret = gendb_search(trusted_domain_state->policy->sam_ldb,
1212 mem_ctx, policy_state->system_dn, &msgs, attrs,
1213 "(&(securityIdentifier=%s)(objectclass=trustedDomain))",
1216 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1220 DEBUG(0,("Found %d records matching DN %s\n", ret,
1221 ldb_dn_get_linearized(policy_state->system_dn)));
1222 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1225 trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msgs[0]->dn);
1227 trusted_domain_state->trusted_domain_user_dn = NULL;
1229 if (ldb_msg_find_attr_as_int(msgs[0], "trustDirection", 0) & LSA_TRUST_DIRECTION_INBOUND) {
1230 const char *flatname = ldb_binary_encode_string(mem_ctx, ldb_msg_find_attr_as_string(msgs[0], "flatname", NULL));
1231 /* search for the trusted_domain record */
1232 ret = gendb_search(trusted_domain_state->policy->sam_ldb,
1233 mem_ctx, policy_state->domain_dn, &msgs, attrs,
1234 "(&(samaccountname=%s$)(objectclass=user)(userAccountControl:1.2.840.113556.1.4.803:=%u))",
1235 flatname, UF_INTERDOMAIN_TRUST_ACCOUNT);
1237 trusted_domain_state->trusted_domain_user_dn = talloc_steal(trusted_domain_state, msgs[0]->dn);
1240 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1242 return NT_STATUS_NO_MEMORY;
1245 handle->data = talloc_steal(handle, trusted_domain_state);
1247 trusted_domain_state->access_mask = r->in.access_mask;
1248 trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
1250 *r->out.trustdom_handle = handle->wire_handle;
1252 return NT_STATUS_OK;
1257 lsa_OpenTrustedDomainByName
1259 static NTSTATUS dcesrv_lsa_OpenTrustedDomainByName(struct dcesrv_call_state *dce_call,
1260 TALLOC_CTX *mem_ctx,
1261 struct lsa_OpenTrustedDomainByName *r)
1263 struct dcesrv_handle *policy_handle;
1265 struct lsa_policy_state *policy_state;
1266 struct lsa_trusted_domain_state *trusted_domain_state;
1267 struct dcesrv_handle *handle;
1268 struct ldb_message **msgs;
1269 const char *attrs[] = {
1275 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1276 ZERO_STRUCTP(r->out.trustdom_handle);
1277 policy_state = policy_handle->data;
1279 if (!r->in.name.string) {
1280 return NT_STATUS_INVALID_PARAMETER;
1283 trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
1284 if (!trusted_domain_state) {
1285 return NT_STATUS_NO_MEMORY;
1287 trusted_domain_state->policy = policy_state;
1289 /* search for the trusted_domain record */
1290 td_name = ldb_binary_encode_string(mem_ctx, r->in.name.string);
1291 ret = gendb_search(trusted_domain_state->policy->sam_ldb,
1292 mem_ctx, policy_state->system_dn, &msgs, attrs,
1293 "(&(|(flatname=%s)(cn=%s)(trustPartner=%s))"
1294 "(objectclass=trustedDomain))",
1295 td_name, td_name, td_name);
1297 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1301 DEBUG(0,("Found %d records matching DN %s\n", ret,
1302 ldb_dn_get_linearized(policy_state->system_dn)));
1303 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1306 /* TODO: perform access checks */
1308 trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msgs[0]->dn);
1310 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1312 return NT_STATUS_NO_MEMORY;
1315 handle->data = talloc_steal(handle, trusted_domain_state);
1317 trusted_domain_state->access_mask = r->in.access_mask;
1318 trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
1320 *r->out.trustdom_handle = handle->wire_handle;
1322 return NT_STATUS_OK;
1328 lsa_SetTrustedDomainInfo
1330 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1331 struct lsa_SetTrustedDomainInfo *r)
1333 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1338 /* parameters 4 to 6 are optional if the dn is a dn of a TDO object,
1339 * otherwise at least one must be provided */
1340 static NTSTATUS get_tdo(struct ldb_context *sam, TALLOC_CTX *mem_ctx,
1341 struct ldb_dn *basedn, const char *dns_domain,
1342 const char *netbios, struct dom_sid2 *sid,
1343 struct ldb_message ***msgs)
1345 const char *attrs[] = { "flatname", "trustPartner",
1346 "securityIdentifier", "trustDirection",
1347 "trustType", "trustAttributes",
1349 "msDs-supportedEncryptionTypes", NULL };
1352 char *sidstr = NULL;
1357 if (dns_domain || netbios || sid) {
1358 filter = talloc_strdup(mem_ctx,
1359 "(&(objectclass=trustedDomain)(|");
1361 filter = talloc_strdup(mem_ctx,
1362 "(objectclass=trustedDomain)");
1365 return NT_STATUS_NO_MEMORY;
1369 dns = ldb_binary_encode_string(mem_ctx, dns_domain);
1371 return NT_STATUS_NO_MEMORY;
1373 filter = talloc_asprintf_append(filter,
1374 "(trustPartner=%s)", dns);
1376 return NT_STATUS_NO_MEMORY;
1380 nbn = ldb_binary_encode_string(mem_ctx, netbios);
1382 return NT_STATUS_NO_MEMORY;
1384 filter = talloc_asprintf_append(filter,
1385 "(flatname=%s)", nbn);
1387 return NT_STATUS_NO_MEMORY;
1391 sidstr = dom_sid_string(mem_ctx, sid);
1393 return NT_STATUS_INVALID_PARAMETER;
1395 filter = talloc_asprintf_append(filter,
1396 "(securityIdentifier=%s)",
1399 return NT_STATUS_NO_MEMORY;
1402 if (dns_domain || netbios || sid) {
1403 filter = talloc_asprintf_append(filter, "))");
1405 return NT_STATUS_NO_MEMORY;
1409 ret = gendb_search(sam, mem_ctx, basedn, msgs, attrs, "%s", filter);
1411 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1415 return NT_STATUS_OBJECT_NAME_COLLISION;
1418 return NT_STATUS_OK;
1421 static NTSTATUS update_uint32_t_value(TALLOC_CTX *mem_ctx,
1422 struct ldb_context *sam_ldb,
1423 struct ldb_message *orig,
1424 struct ldb_message *dest,
1425 const char *attribute,
1427 uint32_t *orig_value)
1429 const struct ldb_val *orig_val;
1430 uint32_t orig_uint = 0;
1434 orig_val = ldb_msg_find_ldb_val(orig, attribute);
1435 if (!orig_val || !orig_val->data) {
1436 /* add new attribute */
1437 flags = LDB_FLAG_MOD_ADD;
1441 orig_uint = strtoul((const char *)orig_val->data, NULL, 0);
1442 if (errno != 0 || orig_uint != value) {
1443 /* replace also if can't get value */
1444 flags = LDB_FLAG_MOD_REPLACE;
1449 /* stored value is identical, nothing to change */
1453 ret = ldb_msg_add_empty(dest, attribute, flags, NULL);
1454 if (ret != LDB_SUCCESS) {
1455 return NT_STATUS_NO_MEMORY;
1458 ret = samdb_msg_add_uint(sam_ldb, dest, dest, attribute, value);
1459 if (ret != LDB_SUCCESS) {
1460 return NT_STATUS_NO_MEMORY;
1465 *orig_value = orig_uint;
1467 return NT_STATUS_OK;
1470 static NTSTATUS update_trust_user(TALLOC_CTX *mem_ctx,
1471 struct ldb_context *sam_ldb,
1472 struct ldb_dn *base_dn,
1474 const char *netbios_name,
1475 struct trustAuthInOutBlob *in)
1477 const char *attrs[] = { "userAccountControl", NULL };
1478 struct ldb_message **msgs;
1479 struct ldb_message *msg;
1484 ret = gendb_search(sam_ldb, mem_ctx,
1485 base_dn, &msgs, attrs,
1486 "samAccountName=%s$", netbios_name);
1488 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1493 return NT_STATUS_OK;
1496 /* ok no existing user, add it from scratch */
1497 return add_trust_user(mem_ctx, sam_ldb, base_dn,
1498 netbios_name, in, NULL);
1501 /* check user is what we are looking for */
1502 uac = ldb_msg_find_attr_as_uint(msgs[0],
1503 "userAccountControl", 0);
1504 if (!(uac & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
1505 return NT_STATUS_OBJECT_NAME_COLLISION;
1509 ret = ldb_delete(sam_ldb, msgs[0]->dn);
1512 return NT_STATUS_OK;
1513 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1514 return NT_STATUS_ACCESS_DENIED;
1516 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1520 /* entry exists, just modify secret if any */
1521 if (in->count == 0) {
1522 return NT_STATUS_OK;
1525 msg = ldb_msg_new(mem_ctx);
1527 return NT_STATUS_NO_MEMORY;
1529 msg->dn = msgs[0]->dn;
1531 for (i = 0; i < in->count; i++) {
1532 const char *attribute;
1534 switch (in->current.array[i].AuthType) {
1535 case TRUST_AUTH_TYPE_NT4OWF:
1536 attribute = "unicodePwd";
1537 v.data = (uint8_t *)&in->current.array[i].AuthInfo.nt4owf.password;
1540 case TRUST_AUTH_TYPE_CLEAR:
1541 attribute = "clearTextPassword";
1542 v.data = in->current.array[i].AuthInfo.clear.password;
1543 v.length = in->current.array[i].AuthInfo.clear.size;
1549 ret = ldb_msg_add_empty(msg, attribute,
1550 LDB_FLAG_MOD_REPLACE, NULL);
1551 if (ret != LDB_SUCCESS) {
1552 return NT_STATUS_NO_MEMORY;
1555 ret = ldb_msg_add_value(msg, attribute, &v, NULL);
1556 if (ret != LDB_SUCCESS) {
1557 return NT_STATUS_NO_MEMORY;
1561 /* create the trusted_domain user account */
1562 ret = ldb_modify(sam_ldb, msg);
1563 if (ret != LDB_SUCCESS) {
1564 DEBUG(0,("Failed to create user record %s: %s\n",
1565 ldb_dn_get_linearized(msg->dn),
1566 ldb_errstring(sam_ldb)));
1569 case LDB_ERR_ENTRY_ALREADY_EXISTS:
1570 return NT_STATUS_DOMAIN_EXISTS;
1571 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1572 return NT_STATUS_ACCESS_DENIED;
1574 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1578 return NT_STATUS_OK;
1582 static NTSTATUS setInfoTrustedDomain_base(struct dcesrv_call_state *dce_call,
1583 struct dcesrv_handle *p_handle,
1584 TALLOC_CTX *mem_ctx,
1585 struct ldb_message *dom_msg,
1586 enum lsa_TrustDomInfoEnum level,
1587 union lsa_TrustedDomainInfo *info)
1589 struct lsa_policy_state *p_state = p_handle->data;
1590 uint32_t *posix_offset = NULL;
1591 struct lsa_TrustDomainInfoInfoEx *info_ex = NULL;
1592 struct lsa_TrustDomainInfoAuthInfo *auth_info = NULL;
1593 struct lsa_TrustDomainInfoAuthInfoInternal *auth_info_int = NULL;
1594 uint32_t *enc_types = NULL;
1595 DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
1596 struct trustDomainPasswords auth_struct;
1598 struct ldb_message **msgs;
1599 struct ldb_message *msg;
1600 bool add_outgoing = false;
1601 bool add_incoming = false;
1602 bool del_outgoing = false;
1603 bool del_incoming = false;
1604 bool in_transaction = false;
1609 case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
1610 posix_offset = &info->posix_offset.posix_offset;
1612 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
1613 info_ex = &info->info_ex;
1615 case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO:
1616 auth_info = &info->auth_info;
1618 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
1619 posix_offset = &info->full_info.posix_offset.posix_offset;
1620 info_ex = &info->full_info.info_ex;
1621 auth_info = &info->full_info.auth_info;
1623 case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO_INTERNAL:
1624 auth_info_int = &info->auth_info_internal;
1626 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_INTERNAL:
1627 posix_offset = &info->full_info_internal.posix_offset.posix_offset;
1628 info_ex = &info->full_info_internal.info_ex;
1629 auth_info_int = &info->full_info_internal.auth_info;
1631 case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
1632 enc_types = &info->enc_types.enc_types;
1635 return NT_STATUS_INVALID_PARAMETER;
1639 /* FIXME: not handled yet */
1640 return NT_STATUS_INVALID_PARAMETER;
1643 /* decode auth_info_int if set */
1644 if (auth_info_int) {
1646 /* now decrypt blob */
1647 auth_blob = data_blob_const(auth_info_int->auth_blob.data,
1648 auth_info_int->auth_blob.size);
1650 nt_status = get_trustdom_auth_blob(dce_call, mem_ctx,
1651 &auth_blob, &auth_struct);
1652 if (!NT_STATUS_IS_OK(nt_status)) {
1658 /* verify data matches */
1659 if (info_ex->trust_attributes &
1660 LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
1661 /* TODO: check what behavior level we have */
1662 if (strcasecmp_m(p_state->domain_dns,
1663 p_state->forest_dns) != 0) {
1664 return NT_STATUS_INVALID_DOMAIN_STATE;
1668 ret = samdb_rodc(p_state->sam_ldb, &am_rodc);
1669 if (ret == LDB_SUCCESS && am_rodc) {
1670 return NT_STATUS_NO_SUCH_DOMAIN;
1673 /* verify only one object matches the dns/netbios/sid
1674 * triplet and that this is the one we already have */
1675 nt_status = get_tdo(p_state->sam_ldb, mem_ctx,
1677 info_ex->domain_name.string,
1678 info_ex->netbios_name.string,
1679 info_ex->sid, &msgs);
1680 if (!NT_STATUS_IS_OK(nt_status)) {
1683 if (ldb_dn_compare(dom_msg->dn, msgs[0]->dn) != 0) {
1684 return NT_STATUS_OBJECT_NAME_COLLISION;
1689 /* TODO: should we fetch previous values from the existing entry
1690 * and append them ? */
1691 if (auth_struct.incoming.count) {
1692 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1693 &auth_struct.incoming,
1694 &trustAuthIncoming);
1695 if (!NT_STATUS_IS_OK(nt_status)) {
1699 trustAuthIncoming = data_blob(NULL, 0);
1702 if (auth_struct.outgoing.count) {
1703 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1704 &auth_struct.outgoing,
1705 &trustAuthOutgoing);
1706 if (!NT_STATUS_IS_OK(nt_status)) {
1710 trustAuthOutgoing = data_blob(NULL, 0);
1713 msg = ldb_msg_new(mem_ctx);
1715 return NT_STATUS_NO_MEMORY;
1717 msg->dn = dom_msg->dn;
1720 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1723 *posix_offset, NULL);
1724 if (!NT_STATUS_IS_OK(nt_status)) {
1735 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1738 info_ex->trust_direction,
1740 if (!NT_STATUS_IS_OK(nt_status)) {
1744 tmp = info_ex->trust_direction ^ origdir;
1745 if (tmp & LSA_TRUST_DIRECTION_INBOUND) {
1746 if (origdir & LSA_TRUST_DIRECTION_INBOUND) {
1747 del_incoming = true;
1749 add_incoming = true;
1752 if (tmp & LSA_TRUST_DIRECTION_OUTBOUND) {
1753 if (origdir & LSA_TRUST_DIRECTION_OUTBOUND) {
1754 del_outgoing = true;
1756 add_outgoing = true;
1760 origtype = ldb_msg_find_attr_as_int(dom_msg, "trustType", -1);
1761 if (origtype == -1 || origtype != info_ex->trust_type) {
1762 DEBUG(1, ("Attempted to change trust type! "
1763 "Operation not handled\n"));
1764 return NT_STATUS_INVALID_PARAMETER;
1767 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1770 info_ex->trust_attributes,
1772 if (!NT_STATUS_IS_OK(nt_status)) {
1775 /* TODO: check forestFunctionality from ldb opaque */
1776 /* TODO: check what is set makes sense */
1777 /* for now refuse changes */
1778 if (origattrs == -1 ||
1779 origattrs != info_ex->trust_attributes) {
1780 DEBUG(1, ("Attempted to change trust attributes! "
1781 "Operation not handled\n"));
1782 return NT_STATUS_INVALID_PARAMETER;
1787 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1789 "msDS-SupportedEncryptionTypes",
1791 if (!NT_STATUS_IS_OK(nt_status)) {
1796 if (add_incoming && trustAuthIncoming.data) {
1797 ret = ldb_msg_add_empty(msg, "trustAuthIncoming",
1798 LDB_FLAG_MOD_REPLACE, NULL);
1799 if (ret != LDB_SUCCESS) {
1800 return NT_STATUS_NO_MEMORY;
1802 ret = ldb_msg_add_value(msg, "trustAuthIncoming",
1803 &trustAuthIncoming, NULL);
1804 if (ret != LDB_SUCCESS) {
1805 return NT_STATUS_NO_MEMORY;
1808 if (add_outgoing && trustAuthOutgoing.data) {
1809 ret = ldb_msg_add_empty(msg, "trustAuthIncoming",
1810 LDB_FLAG_MOD_REPLACE, NULL);
1811 if (ret != LDB_SUCCESS) {
1812 return NT_STATUS_NO_MEMORY;
1814 ret = ldb_msg_add_value(msg, "trustAuthOutgoing",
1815 &trustAuthOutgoing, NULL);
1816 if (ret != LDB_SUCCESS) {
1817 return NT_STATUS_NO_MEMORY;
1821 /* start transaction */
1822 ret = ldb_transaction_start(p_state->sam_ldb);
1823 if (ret != LDB_SUCCESS) {
1824 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1826 in_transaction = true;
1828 ret = ldb_modify(p_state->sam_ldb, msg);
1829 if (ret != LDB_SUCCESS) {
1830 DEBUG(1,("Failed to modify trusted domain record %s: %s\n",
1831 ldb_dn_get_linearized(msg->dn),
1832 ldb_errstring(p_state->sam_ldb)));
1833 if (ret == LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS) {
1834 nt_status = NT_STATUS_ACCESS_DENIED;
1836 nt_status = NT_STATUS_INTERNAL_DB_CORRUPTION;
1841 if (add_incoming || del_incoming) {
1842 const char *netbios_name;
1844 netbios_name = ldb_msg_find_attr_as_string(dom_msg,
1846 if (!netbios_name) {
1847 nt_status = NT_STATUS_INVALID_DOMAIN_STATE;
1851 nt_status = update_trust_user(mem_ctx,
1856 &auth_struct.incoming);
1857 if (!NT_STATUS_IS_OK(nt_status)) {
1862 /* ok, all fine, commit transaction and return */
1863 ret = ldb_transaction_commit(p_state->sam_ldb);
1864 if (ret != LDB_SUCCESS) {
1865 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1867 in_transaction = false;
1869 nt_status = NT_STATUS_OK;
1872 if (in_transaction) {
1873 ldb_transaction_cancel(p_state->sam_ldb);
1879 lsa_SetInfomrationTrustedDomain
1881 static NTSTATUS dcesrv_lsa_SetInformationTrustedDomain(
1882 struct dcesrv_call_state *dce_call,
1883 TALLOC_CTX *mem_ctx,
1884 struct lsa_SetInformationTrustedDomain *r)
1886 struct dcesrv_handle *h;
1887 struct lsa_trusted_domain_state *td_state;
1888 struct ldb_message **msgs;
1891 DCESRV_PULL_HANDLE(h, r->in.trustdom_handle,
1892 LSA_HANDLE_TRUSTED_DOMAIN);
1894 td_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
1896 /* get the trusted domain object */
1897 nt_status = get_tdo(td_state->policy->sam_ldb, mem_ctx,
1898 td_state->trusted_domain_dn,
1899 NULL, NULL, NULL, &msgs);
1900 if (!NT_STATUS_IS_OK(nt_status)) {
1901 if (NT_STATUS_EQUAL(nt_status,
1902 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1905 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1908 return setInfoTrustedDomain_base(dce_call, h, mem_ctx,
1909 msgs[0], r->in.level, r->in.info);
1914 lsa_DeleteTrustedDomain
1916 static NTSTATUS dcesrv_lsa_DeleteTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1917 struct lsa_DeleteTrustedDomain *r)
1920 struct lsa_OpenTrustedDomain opn;
1921 struct lsa_DeleteObject del;
1922 struct dcesrv_handle *h;
1924 opn.in.handle = r->in.handle;
1925 opn.in.sid = r->in.dom_sid;
1926 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1927 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
1928 if (!opn.out.trustdom_handle) {
1929 return NT_STATUS_NO_MEMORY;
1931 status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
1932 if (!NT_STATUS_IS_OK(status)) {
1936 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
1937 talloc_steal(mem_ctx, h);
1939 del.in.handle = opn.out.trustdom_handle;
1940 del.out.handle = opn.out.trustdom_handle;
1941 status = dcesrv_lsa_DeleteObject(dce_call, mem_ctx, &del);
1942 if (!NT_STATUS_IS_OK(status)) {
1945 return NT_STATUS_OK;
1948 static NTSTATUS fill_trust_domain_ex(TALLOC_CTX *mem_ctx,
1949 struct ldb_message *msg,
1950 struct lsa_TrustDomainInfoInfoEx *info_ex)
1952 info_ex->domain_name.string
1953 = ldb_msg_find_attr_as_string(msg, "trustPartner", NULL);
1954 info_ex->netbios_name.string
1955 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
1957 = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
1958 info_ex->trust_direction
1959 = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
1961 = ldb_msg_find_attr_as_int(msg, "trustType", 0);
1962 info_ex->trust_attributes
1963 = ldb_msg_find_attr_as_int(msg, "trustAttributes", 0);
1964 return NT_STATUS_OK;
1968 lsa_QueryTrustedDomainInfo
1970 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1971 struct lsa_QueryTrustedDomainInfo *r)
1973 union lsa_TrustedDomainInfo *info = NULL;
1974 struct dcesrv_handle *h;
1975 struct lsa_trusted_domain_state *trusted_domain_state;
1976 struct ldb_message *msg;
1978 struct ldb_message **res;
1979 const char *attrs[] = {
1982 "securityIdentifier",
1986 "msDs-supportedEncryptionTypes",
1990 DCESRV_PULL_HANDLE(h, r->in.trustdom_handle, LSA_HANDLE_TRUSTED_DOMAIN);
1992 trusted_domain_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
1994 /* pull all the user attributes */
1995 ret = gendb_search_dn(trusted_domain_state->policy->sam_ldb, mem_ctx,
1996 trusted_domain_state->trusted_domain_dn, &res, attrs);
1998 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2002 info = talloc_zero(mem_ctx, union lsa_TrustedDomainInfo);
2004 return NT_STATUS_NO_MEMORY;
2006 *r->out.info = info;
2008 switch (r->in.level) {
2009 case LSA_TRUSTED_DOMAIN_INFO_NAME:
2010 info->name.netbios_name.string
2011 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2013 case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
2014 info->posix_offset.posix_offset
2015 = ldb_msg_find_attr_as_uint(msg, "posixOffset", 0);
2017 #if 0 /* Win2k3 doesn't implement this */
2018 case LSA_TRUSTED_DOMAIN_INFO_BASIC:
2019 r->out.info->info_basic.netbios_name.string
2020 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2021 r->out.info->info_basic.sid
2022 = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
2025 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
2026 return fill_trust_domain_ex(mem_ctx, msg, &info->info_ex);
2028 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
2029 ZERO_STRUCT(info->full_info);
2030 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info.info_ex);
2031 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_2_INTERNAL:
2032 ZERO_STRUCT(info->full_info2_internal);
2033 info->full_info2_internal.posix_offset.posix_offset
2034 = ldb_msg_find_attr_as_uint(msg, "posixOffset", 0);
2035 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info2_internal.info.info_ex);
2037 case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
2038 info->enc_types.enc_types
2039 = ldb_msg_find_attr_as_uint(msg, "msDs-supportedEncryptionTypes", KERB_ENCTYPE_RC4_HMAC_MD5);
2042 case LSA_TRUSTED_DOMAIN_INFO_CONTROLLERS:
2043 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX2_INTERNAL:
2044 /* oops, we don't want to return the info after all */
2046 *r->out.info = NULL;
2047 return NT_STATUS_INVALID_PARAMETER;
2049 /* oops, we don't want to return the info after all */
2051 *r->out.info = NULL;
2052 return NT_STATUS_INVALID_INFO_CLASS;
2055 return NT_STATUS_OK;
2060 lsa_QueryTrustedDomainInfoBySid
2062 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoBySid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2063 struct lsa_QueryTrustedDomainInfoBySid *r)
2066 struct lsa_OpenTrustedDomain opn;
2067 struct lsa_QueryTrustedDomainInfo query;
2068 struct dcesrv_handle *h;
2070 opn.in.handle = r->in.handle;
2071 opn.in.sid = r->in.dom_sid;
2072 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2073 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2074 if (!opn.out.trustdom_handle) {
2075 return NT_STATUS_NO_MEMORY;
2077 status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
2078 if (!NT_STATUS_IS_OK(status)) {
2082 /* Ensure this handle goes away at the end of this call */
2083 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2084 talloc_steal(mem_ctx, h);
2086 query.in.trustdom_handle = opn.out.trustdom_handle;
2087 query.in.level = r->in.level;
2088 query.out.info = r->out.info;
2089 status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2090 if (!NT_STATUS_IS_OK(status)) {
2094 return NT_STATUS_OK;
2098 lsa_SetTrustedDomainInfoByName
2100 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2101 TALLOC_CTX *mem_ctx,
2102 struct lsa_SetTrustedDomainInfoByName *r)
2104 struct dcesrv_handle *policy_handle;
2105 struct lsa_policy_state *policy_state;
2106 struct ldb_message **msgs;
2109 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2110 policy_state = policy_handle->data;
2112 /* get the trusted domain object */
2113 nt_status = get_tdo(policy_state->sam_ldb, mem_ctx,
2114 policy_state->domain_dn,
2115 r->in.trusted_domain->string,
2116 r->in.trusted_domain->string,
2118 if (!NT_STATUS_IS_OK(nt_status)) {
2119 if (NT_STATUS_EQUAL(nt_status,
2120 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2123 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2126 return setInfoTrustedDomain_base(dce_call, policy_handle, mem_ctx,
2127 msgs[0], r->in.level, r->in.info);
2131 lsa_QueryTrustedDomainInfoByName
2133 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2134 TALLOC_CTX *mem_ctx,
2135 struct lsa_QueryTrustedDomainInfoByName *r)
2138 struct lsa_OpenTrustedDomainByName opn;
2139 struct lsa_QueryTrustedDomainInfo query;
2140 struct dcesrv_handle *h;
2142 opn.in.handle = r->in.handle;
2143 opn.in.name = *r->in.trusted_domain;
2144 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2145 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2146 if (!opn.out.trustdom_handle) {
2147 return NT_STATUS_NO_MEMORY;
2149 status = dcesrv_lsa_OpenTrustedDomainByName(dce_call, mem_ctx, &opn);
2150 if (!NT_STATUS_IS_OK(status)) {
2154 /* Ensure this handle goes away at the end of this call */
2155 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2156 talloc_steal(mem_ctx, h);
2158 query.in.trustdom_handle = opn.out.trustdom_handle;
2159 query.in.level = r->in.level;
2160 query.out.info = r->out.info;
2161 status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2162 if (!NT_STATUS_IS_OK(status)) {
2166 return NT_STATUS_OK;
2170 lsa_CloseTrustedDomainEx
2172 static NTSTATUS dcesrv_lsa_CloseTrustedDomainEx(struct dcesrv_call_state *dce_call,
2173 TALLOC_CTX *mem_ctx,
2174 struct lsa_CloseTrustedDomainEx *r)
2176 /* The result of a bad hair day from an IDL programmer? Not
2177 * implmented in Win2k3. You should always just lsa_Close
2179 return NT_STATUS_NOT_IMPLEMENTED;
2184 comparison function for sorting lsa_DomainInformation array
2186 static int compare_DomainInfo(struct lsa_DomainInfo *e1, struct lsa_DomainInfo *e2)
2188 return strcasecmp_m(e1->name.string, e2->name.string);
2194 static NTSTATUS dcesrv_lsa_EnumTrustDom(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2195 struct lsa_EnumTrustDom *r)
2197 struct dcesrv_handle *policy_handle;
2198 struct lsa_DomainInfo *entries;
2199 struct lsa_policy_state *policy_state;
2200 struct ldb_message **domains;
2201 const char *attrs[] = {
2203 "securityIdentifier",
2210 *r->out.resume_handle = 0;
2212 r->out.domains->domains = NULL;
2213 r->out.domains->count = 0;
2215 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2217 policy_state = policy_handle->data;
2219 /* search for all users in this domain. This could possibly be cached and
2220 resumed based on resume_key */
2221 count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
2222 "objectclass=trustedDomain");
2224 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2227 /* convert to lsa_TrustInformation format */
2228 entries = talloc_array(mem_ctx, struct lsa_DomainInfo, count);
2230 return NT_STATUS_NO_MEMORY;
2232 for (i=0;i<count;i++) {
2233 entries[i].sid = samdb_result_dom_sid(mem_ctx, domains[i], "securityIdentifier");
2234 entries[i].name.string = ldb_msg_find_attr_as_string(domains[i], "flatname", NULL);
2237 /* sort the results by name */
2238 TYPESAFE_QSORT(entries, count, compare_DomainInfo);
2240 if (*r->in.resume_handle >= count) {
2241 *r->out.resume_handle = -1;
2243 return NT_STATUS_NO_MORE_ENTRIES;
2246 /* return the rest, limit by max_size. Note that we
2247 use the w2k3 element size value of 60 */
2248 r->out.domains->count = count - *r->in.resume_handle;
2249 r->out.domains->count = MIN(r->out.domains->count,
2250 1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_MULTIPLIER));
2252 r->out.domains->domains = entries + *r->in.resume_handle;
2253 r->out.domains->count = r->out.domains->count;
2255 if (r->out.domains->count < count - *r->in.resume_handle) {
2256 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2257 return STATUS_MORE_ENTRIES;
2260 /* according to MS-LSAD 3.1.4.7.8 output resume handle MUST
2261 * always be larger than the previous input resume handle, in
2262 * particular when hitting the last query it is vital to set the
2263 * resume handle correctly to avoid infinite client loops, as
2264 * seen e.g. with Windows XP SP3 when resume handle is 0 and
2265 * status is NT_STATUS_OK - gd */
2267 *r->out.resume_handle = (uint32_t)-1;
2269 return NT_STATUS_OK;
2273 comparison function for sorting lsa_DomainInformation array
2275 static int compare_TrustDomainInfoInfoEx(struct lsa_TrustDomainInfoInfoEx *e1, struct lsa_TrustDomainInfoInfoEx *e2)
2277 return strcasecmp_m(e1->netbios_name.string, e2->netbios_name.string);
2281 lsa_EnumTrustedDomainsEx
2283 static NTSTATUS dcesrv_lsa_EnumTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2284 struct lsa_EnumTrustedDomainsEx *r)
2286 struct dcesrv_handle *policy_handle;
2287 struct lsa_TrustDomainInfoInfoEx *entries;
2288 struct lsa_policy_state *policy_state;
2289 struct ldb_message **domains;
2290 const char *attrs[] = {
2293 "securityIdentifier",
2303 *r->out.resume_handle = 0;
2305 r->out.domains->domains = NULL;
2306 r->out.domains->count = 0;
2308 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2310 policy_state = policy_handle->data;
2312 /* search for all users in this domain. This could possibly be cached and
2313 resumed based on resume_key */
2314 count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
2315 "objectclass=trustedDomain");
2317 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2320 /* convert to lsa_DomainInformation format */
2321 entries = talloc_array(mem_ctx, struct lsa_TrustDomainInfoInfoEx, count);
2323 return NT_STATUS_NO_MEMORY;
2325 for (i=0;i<count;i++) {
2326 nt_status = fill_trust_domain_ex(mem_ctx, domains[i], &entries[i]);
2327 if (!NT_STATUS_IS_OK(nt_status)) {
2332 /* sort the results by name */
2333 TYPESAFE_QSORT(entries, count, compare_TrustDomainInfoInfoEx);
2335 if (*r->in.resume_handle >= count) {
2336 *r->out.resume_handle = -1;
2338 return NT_STATUS_NO_MORE_ENTRIES;
2341 /* return the rest, limit by max_size. Note that we
2342 use the w2k3 element size value of 60 */
2343 r->out.domains->count = count - *r->in.resume_handle;
2344 r->out.domains->count = MIN(r->out.domains->count,
2345 1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_EX_MULTIPLIER));
2347 r->out.domains->domains = entries + *r->in.resume_handle;
2348 r->out.domains->count = r->out.domains->count;
2350 if (r->out.domains->count < count - *r->in.resume_handle) {
2351 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2352 return STATUS_MORE_ENTRIES;
2355 return NT_STATUS_OK;
2362 static NTSTATUS dcesrv_lsa_OpenAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2363 struct lsa_OpenAccount *r)
2365 struct dcesrv_handle *h, *ah;
2366 struct lsa_policy_state *state;
2367 struct lsa_account_state *astate;
2369 ZERO_STRUCTP(r->out.acct_handle);
2371 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2375 astate = talloc(dce_call->conn, struct lsa_account_state);
2376 if (astate == NULL) {
2377 return NT_STATUS_NO_MEMORY;
2380 astate->account_sid = dom_sid_dup(astate, r->in.sid);
2381 if (astate->account_sid == NULL) {
2382 talloc_free(astate);
2383 return NT_STATUS_NO_MEMORY;
2386 astate->policy = talloc_reference(astate, state);
2387 astate->access_mask = r->in.access_mask;
2389 ah = dcesrv_handle_new(dce_call->context, LSA_HANDLE_ACCOUNT);
2391 talloc_free(astate);
2392 return NT_STATUS_NO_MEMORY;
2395 ah->data = talloc_steal(ah, astate);
2397 *r->out.acct_handle = ah->wire_handle;
2399 return NT_STATUS_OK;
2404 lsa_EnumPrivsAccount
2406 static NTSTATUS dcesrv_lsa_EnumPrivsAccount(struct dcesrv_call_state *dce_call,
2407 TALLOC_CTX *mem_ctx,
2408 struct lsa_EnumPrivsAccount *r)
2410 struct dcesrv_handle *h;
2411 struct lsa_account_state *astate;
2414 struct ldb_message **res;
2415 const char * const attrs[] = { "privilege", NULL};
2416 struct ldb_message_element *el;
2418 struct lsa_PrivilegeSet *privs;
2420 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2424 privs = talloc(mem_ctx, struct lsa_PrivilegeSet);
2425 if (privs == NULL) {
2426 return NT_STATUS_NO_MEMORY;
2432 *r->out.privs = privs;
2434 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
2435 if (sidstr == NULL) {
2436 return NT_STATUS_NO_MEMORY;
2439 ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs,
2440 "objectSid=%s", sidstr);
2442 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2445 return NT_STATUS_OK;
2448 el = ldb_msg_find_element(res[0], "privilege");
2449 if (el == NULL || el->num_values == 0) {
2450 return NT_STATUS_OK;
2453 privs->set = talloc_array(privs,
2454 struct lsa_LUIDAttribute, el->num_values);
2455 if (privs->set == NULL) {
2456 return NT_STATUS_NO_MEMORY;
2460 for (i=0;i<el->num_values;i++) {
2461 int id = sec_privilege_id((const char *)el->values[i].data);
2462 if (id == SEC_PRIV_INVALID) {
2463 /* Perhaps an account right, not a privilege */
2466 privs->set[j].attribute = 0;
2467 privs->set[j].luid.low = id;
2468 privs->set[j].luid.high = 0;
2474 return NT_STATUS_OK;
2478 lsa_EnumAccountRights
2480 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call,
2481 TALLOC_CTX *mem_ctx,
2482 struct lsa_EnumAccountRights *r)
2484 struct dcesrv_handle *h;
2485 struct lsa_policy_state *state;
2488 struct ldb_message **res;
2489 const char * const attrs[] = { "privilege", NULL};
2491 struct ldb_message_element *el;
2493 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2497 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, r->in.sid);
2498 if (sidstr == NULL) {
2499 return NT_STATUS_NO_MEMORY;
2502 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
2503 "(&(objectSid=%s)(privilege=*))", sidstr);
2505 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2508 DEBUG(3, ("searching for account rights for SID: %s failed: %s",
2509 dom_sid_string(mem_ctx, r->in.sid),
2510 ldb_errstring(state->pdb)));
2511 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2514 el = ldb_msg_find_element(res[0], "privilege");
2515 if (el == NULL || el->num_values == 0) {
2516 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2519 r->out.rights->count = el->num_values;
2520 r->out.rights->names = talloc_array(r->out.rights,
2521 struct lsa_StringLarge, r->out.rights->count);
2522 if (r->out.rights->names == NULL) {
2523 return NT_STATUS_NO_MEMORY;
2526 for (i=0;i<el->num_values;i++) {
2527 r->out.rights->names[i].string = (const char *)el->values[i].data;
2530 return NT_STATUS_OK;
2536 helper for lsa_AddAccountRights and lsa_RemoveAccountRights
2538 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
2539 TALLOC_CTX *mem_ctx,
2540 struct lsa_policy_state *state,
2542 struct dom_sid *sid,
2543 const struct lsa_RightSet *rights)
2545 const char *sidstr, *sidndrstr;
2546 struct ldb_message *msg;
2547 struct ldb_message_element *el;
2550 struct lsa_EnumAccountRights r2;
2553 if (security_session_user_level(dce_call->conn->auth_state.session_info, NULL) <
2554 SECURITY_ADMINISTRATOR) {
2555 DEBUG(0,("lsa_AddRemoveAccount refused for supplied security token\n"));
2556 return NT_STATUS_ACCESS_DENIED;
2559 msg = ldb_msg_new(mem_ctx);
2561 return NT_STATUS_NO_MEMORY;
2564 sidndrstr = ldap_encode_ndr_dom_sid(msg, sid);
2565 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sidndrstr, msg);
2567 sidstr = dom_sid_string(msg, sid);
2568 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sidstr, msg);
2570 dnstr = talloc_asprintf(msg, "sid=%s", sidstr);
2571 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(dnstr, msg);
2573 msg->dn = ldb_dn_new(msg, state->pdb, dnstr);
2574 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(msg->dn, msg);
2576 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2579 r2.in.handle = &state->handle->wire_handle;
2581 r2.out.rights = talloc(mem_ctx, struct lsa_RightSet);
2583 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
2584 if (!NT_STATUS_IS_OK(status)) {
2585 ZERO_STRUCTP(r2.out.rights);
2589 for (i=0;i<rights->count;i++) {
2590 if (sec_privilege_id(rights->names[i].string) == SEC_PRIV_INVALID) {
2591 if (sec_right_bit(rights->names[i].string) == 0) {
2593 return NT_STATUS_NO_SUCH_PRIVILEGE;
2597 return NT_STATUS_NO_SUCH_PRIVILEGE;
2600 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2602 for (j=0;j<r2.out.rights->count;j++) {
2603 if (strcasecmp_m(r2.out.rights->names[j].string,
2604 rights->names[i].string) == 0) {
2608 if (j != r2.out.rights->count) continue;
2611 ret = ldb_msg_add_string(msg, "privilege", rights->names[i].string);
2612 if (ret != LDB_SUCCESS) {
2614 return NT_STATUS_NO_MEMORY;
2618 el = ldb_msg_find_element(msg, "privilege");
2621 return NT_STATUS_OK;
2624 el->flags = ldb_flag;
2626 ret = ldb_modify(state->pdb, msg);
2627 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
2628 if (samdb_msg_add_dom_sid(state->pdb, msg, msg, "objectSid", sid) != LDB_SUCCESS) {
2630 return NT_STATUS_NO_MEMORY;
2632 samdb_msg_add_string(state->pdb, msg, msg, "comment", "added via LSA");
2633 ret = ldb_add(state->pdb, msg);
2635 if (ret != LDB_SUCCESS) {
2636 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE && ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
2638 return NT_STATUS_OK;
2640 DEBUG(3, ("Could not %s attributes from %s: %s",
2641 LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE ? "delete" : "add",
2642 ldb_dn_get_linearized(msg->dn), ldb_errstring(state->pdb)));
2644 return NT_STATUS_UNEXPECTED_IO_ERROR;
2648 return NT_STATUS_OK;
2652 lsa_AddPrivilegesToAccount
2654 static NTSTATUS dcesrv_lsa_AddPrivilegesToAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2655 struct lsa_AddPrivilegesToAccount *r)
2657 struct lsa_RightSet rights;
2658 struct dcesrv_handle *h;
2659 struct lsa_account_state *astate;
2662 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2666 rights.count = r->in.privs->count;
2667 rights.names = talloc_array(mem_ctx, struct lsa_StringLarge, rights.count);
2668 if (rights.names == NULL) {
2669 return NT_STATUS_NO_MEMORY;
2671 for (i=0;i<rights.count;i++) {
2672 int id = r->in.privs->set[i].luid.low;
2673 if (r->in.privs->set[i].luid.high) {
2674 return NT_STATUS_NO_SUCH_PRIVILEGE;
2676 rights.names[i].string = sec_privilege_name(id);
2677 if (rights.names[i].string == NULL) {
2678 return NT_STATUS_NO_SUCH_PRIVILEGE;
2682 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
2683 LDB_FLAG_MOD_ADD, astate->account_sid,
2689 lsa_RemovePrivilegesFromAccount
2691 static NTSTATUS dcesrv_lsa_RemovePrivilegesFromAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2692 struct lsa_RemovePrivilegesFromAccount *r)
2694 struct lsa_RightSet *rights;
2695 struct dcesrv_handle *h;
2696 struct lsa_account_state *astate;
2699 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2703 rights = talloc(mem_ctx, struct lsa_RightSet);
2705 if (r->in.remove_all == 1 &&
2706 r->in.privs == NULL) {
2707 struct lsa_EnumAccountRights r2;
2710 r2.in.handle = &astate->policy->handle->wire_handle;
2711 r2.in.sid = astate->account_sid;
2712 r2.out.rights = rights;
2714 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
2715 if (!NT_STATUS_IS_OK(status)) {
2719 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
2720 LDB_FLAG_MOD_DELETE, astate->account_sid,
2724 if (r->in.remove_all != 0) {
2725 return NT_STATUS_INVALID_PARAMETER;
2728 rights->count = r->in.privs->count;
2729 rights->names = talloc_array(mem_ctx, struct lsa_StringLarge, rights->count);
2730 if (rights->names == NULL) {
2731 return NT_STATUS_NO_MEMORY;
2733 for (i=0;i<rights->count;i++) {
2734 int id = r->in.privs->set[i].luid.low;
2735 if (r->in.privs->set[i].luid.high) {
2736 return NT_STATUS_NO_SUCH_PRIVILEGE;
2738 rights->names[i].string = sec_privilege_name(id);
2739 if (rights->names[i].string == NULL) {
2740 return NT_STATUS_NO_SUCH_PRIVILEGE;
2744 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
2745 LDB_FLAG_MOD_DELETE, astate->account_sid,
2751 lsa_GetQuotasForAccount
2753 static NTSTATUS dcesrv_lsa_GetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2754 struct lsa_GetQuotasForAccount *r)
2756 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2761 lsa_SetQuotasForAccount
2763 static NTSTATUS dcesrv_lsa_SetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2764 struct lsa_SetQuotasForAccount *r)
2766 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2771 lsa_GetSystemAccessAccount
2773 static NTSTATUS dcesrv_lsa_GetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2774 struct lsa_GetSystemAccessAccount *r)
2776 struct dcesrv_handle *h;
2777 struct lsa_account_state *astate;
2780 struct ldb_message **res;
2781 const char * const attrs[] = { "privilege", NULL};
2782 struct ldb_message_element *el;
2785 *(r->out.access_mask) = 0x00000000;
2787 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2791 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
2792 if (sidstr == NULL) {
2793 return NT_STATUS_NO_MEMORY;
2796 ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs,
2797 "objectSid=%s", sidstr);
2799 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2802 return NT_STATUS_OK;
2805 el = ldb_msg_find_element(res[0], "privilege");
2806 if (el == NULL || el->num_values == 0) {
2807 return NT_STATUS_OK;
2810 for (i=0;i<el->num_values;i++) {
2811 uint32_t right_bit = sec_right_bit((const char *)el->values[i].data);
2812 if (right_bit == 0) {
2813 /* Perhaps an privilege, not a right */
2816 *(r->out.access_mask) |= right_bit;
2819 return NT_STATUS_OK;
2824 lsa_SetSystemAccessAccount
2826 static NTSTATUS dcesrv_lsa_SetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2827 struct lsa_SetSystemAccessAccount *r)
2829 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2836 static NTSTATUS dcesrv_lsa_CreateSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2837 struct lsa_CreateSecret *r)
2839 struct dcesrv_handle *policy_handle;
2840 struct lsa_policy_state *policy_state;
2841 struct lsa_secret_state *secret_state;
2842 struct dcesrv_handle *handle;
2843 struct ldb_message **msgs, *msg;
2844 const char *attrs[] = {
2852 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2853 ZERO_STRUCTP(r->out.sec_handle);
2855 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
2857 case SECURITY_SYSTEM:
2858 case SECURITY_ADMINISTRATOR:
2861 /* Users and annonymous are not allowed create secrets */
2862 return NT_STATUS_ACCESS_DENIED;
2865 policy_state = policy_handle->data;
2867 if (!r->in.name.string) {
2868 return NT_STATUS_INVALID_PARAMETER;
2871 secret_state = talloc(mem_ctx, struct lsa_secret_state);
2872 NT_STATUS_HAVE_NO_MEMORY(secret_state);
2873 secret_state->policy = policy_state;
2875 msg = ldb_msg_new(mem_ctx);
2877 return NT_STATUS_NO_MEMORY;
2880 if (strncmp("G$", r->in.name.string, 2) == 0) {
2883 secret_state->global = true;
2885 name = &r->in.name.string[2];
2886 if (strlen(name) == 0) {
2887 return NT_STATUS_INVALID_PARAMETER;
2890 name2 = talloc_asprintf(mem_ctx, "%s Secret",
2891 ldb_binary_encode_string(mem_ctx, name));
2892 NT_STATUS_HAVE_NO_MEMORY(name2);
2894 /* We need to connect to the database as system, as this is one
2895 * of the rare RPC calls that must read the secrets (and this
2896 * is denied otherwise) */
2897 secret_state->sam_ldb = talloc_reference(secret_state,
2898 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));
2899 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
2901 /* search for the secret record */
2902 ret = gendb_search(secret_state->sam_ldb,
2903 mem_ctx, policy_state->system_dn, &msgs, attrs,
2904 "(&(cn=%s)(objectclass=secret))",
2907 return NT_STATUS_OBJECT_NAME_COLLISION;
2911 DEBUG(0,("Failure searching for CN=%s: %s\n",
2912 name2, ldb_errstring(secret_state->sam_ldb)));
2913 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2916 msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
2917 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
2918 if (!ldb_dn_add_child_fmt(msg->dn, "cn=%s", name2)) {
2919 return NT_STATUS_NO_MEMORY;
2922 ret = ldb_msg_add_string(msg, "cn", name2);
2923 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
2925 secret_state->global = false;
2927 name = r->in.name.string;
2928 if (strlen(name) == 0) {
2929 return NT_STATUS_INVALID_PARAMETER;
2932 secret_state->sam_ldb = talloc_reference(secret_state,
2933 secrets_db_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
2934 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
2936 /* search for the secret record */
2937 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
2938 ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
2940 "(&(cn=%s)(objectclass=secret))",
2941 ldb_binary_encode_string(mem_ctx, name));
2943 return NT_STATUS_OBJECT_NAME_COLLISION;
2947 DEBUG(0,("Failure searching for CN=%s: %s\n",
2948 name, ldb_errstring(secret_state->sam_ldb)));
2949 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2952 msg->dn = ldb_dn_new_fmt(mem_ctx, secret_state->sam_ldb,
2953 "cn=%s,cn=LSA Secrets", name);
2954 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
2955 ret = ldb_msg_add_string(msg, "cn", name);
2956 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
2959 ret = samdb_msg_add_string(secret_state->sam_ldb, mem_ctx, msg,
2960 "objectClass", "secret");
2961 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
2963 secret_state->secret_dn = talloc_reference(secret_state, msg->dn);
2964 NT_STATUS_HAVE_NO_MEMORY(secret_state->secret_dn);
2966 /* create the secret */
2967 ret = ldb_add(secret_state->sam_ldb, msg);
2968 if (ret != LDB_SUCCESS) {
2969 DEBUG(0,("Failed to create secret record %s: %s\n",
2970 ldb_dn_get_linearized(msg->dn),
2971 ldb_errstring(secret_state->sam_ldb)));
2972 return NT_STATUS_ACCESS_DENIED;
2975 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
2976 NT_STATUS_HAVE_NO_MEMORY(handle);
2978 handle->data = talloc_steal(handle, secret_state);
2980 secret_state->access_mask = r->in.access_mask;
2981 secret_state->policy = talloc_reference(secret_state, policy_state);
2982 NT_STATUS_HAVE_NO_MEMORY(secret_state->policy);
2984 *r->out.sec_handle = handle->wire_handle;
2986 return NT_STATUS_OK;
2993 static NTSTATUS dcesrv_lsa_OpenSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2994 struct lsa_OpenSecret *r)
2996 struct dcesrv_handle *policy_handle;
2998 struct lsa_policy_state *policy_state;
2999 struct lsa_secret_state *secret_state;
3000 struct dcesrv_handle *handle;
3001 struct ldb_message **msgs;
3002 const char *attrs[] = {
3010 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
3011 ZERO_STRUCTP(r->out.sec_handle);
3012 policy_state = policy_handle->data;
3014 if (!r->in.name.string) {
3015 return NT_STATUS_INVALID_PARAMETER;
3018 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3020 case SECURITY_SYSTEM:
3021 case SECURITY_ADMINISTRATOR:
3024 /* Users and annonymous are not allowed to access secrets */
3025 return NT_STATUS_ACCESS_DENIED;
3028 secret_state = talloc(mem_ctx, struct lsa_secret_state);
3029 if (!secret_state) {
3030 return NT_STATUS_NO_MEMORY;
3032 secret_state->policy = policy_state;
3034 if (strncmp("G$", r->in.name.string, 2) == 0) {
3035 name = &r->in.name.string[2];
3036 /* 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) */
3037 secret_state->sam_ldb = talloc_reference(secret_state,
3038 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));
3039 secret_state->global = true;
3041 if (strlen(name) < 1) {
3042 return NT_STATUS_INVALID_PARAMETER;
3045 /* search for the secret record */
3046 ret = gendb_search(secret_state->sam_ldb,
3047 mem_ctx, policy_state->system_dn, &msgs, attrs,
3048 "(&(cn=%s Secret)(objectclass=secret))",
3049 ldb_binary_encode_string(mem_ctx, name));
3051 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3055 DEBUG(0,("Found %d records matching DN %s\n", ret,
3056 ldb_dn_get_linearized(policy_state->system_dn)));
3057 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3061 secret_state->global = false;
3062 secret_state->sam_ldb = talloc_reference(secret_state,
3063 secrets_db_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
3065 name = r->in.name.string;
3066 if (strlen(name) < 1) {
3067 return NT_STATUS_INVALID_PARAMETER;
3070 /* search for the secret record */
3071 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
3072 ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
3074 "(&(cn=%s)(objectclass=secret))",
3075 ldb_binary_encode_string(mem_ctx, name));
3077 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3081 DEBUG(0,("Found %d records matching CN=%s\n",
3082 ret, ldb_binary_encode_string(mem_ctx, name)));
3083 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3087 secret_state->secret_dn = talloc_reference(secret_state, msgs[0]->dn);
3089 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
3091 return NT_STATUS_NO_MEMORY;
3094 handle->data = talloc_steal(handle, secret_state);
3096 secret_state->access_mask = r->in.access_mask;
3097 secret_state->policy = talloc_reference(secret_state, policy_state);
3099 *r->out.sec_handle = handle->wire_handle;
3101 return NT_STATUS_OK;
3108 static NTSTATUS dcesrv_lsa_SetSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3109 struct lsa_SetSecret *r)
3112 struct dcesrv_handle *h;
3113 struct lsa_secret_state *secret_state;
3114 struct ldb_message *msg;
3115 DATA_BLOB session_key;
3116 DATA_BLOB crypt_secret, secret;
3119 NTSTATUS status = NT_STATUS_OK;
3121 struct timeval now = timeval_current();
3122 NTTIME nt_now = timeval_to_nttime(&now);
3124 DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3126 secret_state = h->data;
3128 msg = ldb_msg_new(mem_ctx);
3130 return NT_STATUS_NO_MEMORY;
3133 msg->dn = talloc_reference(mem_ctx, secret_state->secret_dn);
3135 return NT_STATUS_NO_MEMORY;
3137 status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
3138 if (!NT_STATUS_IS_OK(status)) {
3142 if (r->in.old_val) {
3144 crypt_secret.data = r->in.old_val->data;
3145 crypt_secret.length = r->in.old_val->size;
3147 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3148 if (!NT_STATUS_IS_OK(status)) {
3152 val.data = secret.data;
3153 val.length = secret.length;
3156 if (ldb_msg_add_value(msg, "priorValue", &val, NULL) != LDB_SUCCESS) {
3157 return NT_STATUS_NO_MEMORY;
3160 /* set old value mtime */
3161 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3162 mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3163 return NT_STATUS_NO_MEMORY;
3167 /* If the old value is not set, then migrate the
3168 * current value to the old value */
3169 const struct ldb_val *old_val;
3170 NTTIME last_set_time;
3171 struct ldb_message **res;
3172 const char *attrs[] = {
3178 /* search for the secret record */
3179 ret = gendb_search_dn(secret_state->sam_ldb,mem_ctx,
3180 secret_state->secret_dn, &res, attrs);
3182 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3186 DEBUG(0,("Found %d records matching dn=%s\n", ret,
3187 ldb_dn_get_linearized(secret_state->secret_dn)));
3188 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3191 old_val = ldb_msg_find_ldb_val(res[0], "currentValue");
3192 last_set_time = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
3196 if (ldb_msg_add_value(msg, "priorValue",
3197 old_val, NULL) != LDB_SUCCESS) {
3198 return NT_STATUS_NO_MEMORY;
3201 if (samdb_msg_add_delete(secret_state->sam_ldb,
3202 mem_ctx, msg, "priorValue") != LDB_SUCCESS) {
3203 return NT_STATUS_NO_MEMORY;
3208 /* set old value mtime */
3209 if (ldb_msg_find_ldb_val(res[0], "lastSetTime")) {
3210 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3211 mem_ctx, msg, "priorSetTime", last_set_time) != LDB_SUCCESS) {
3212 return NT_STATUS_NO_MEMORY;
3215 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3216 mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3217 return NT_STATUS_NO_MEMORY;
3222 if (r->in.new_val) {
3224 crypt_secret.data = r->in.new_val->data;
3225 crypt_secret.length = r->in.new_val->size;
3227 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3228 if (!NT_STATUS_IS_OK(status)) {
3232 val.data = secret.data;
3233 val.length = secret.length;
3236 if (ldb_msg_add_value(msg, "currentValue", &val, NULL) != LDB_SUCCESS) {
3237 return NT_STATUS_NO_MEMORY;
3240 /* set new value mtime */
3241 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3242 mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3243 return NT_STATUS_NO_MEMORY;
3247 /* NULL out the NEW value */
3248 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3249 mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3250 return NT_STATUS_NO_MEMORY;
3252 if (samdb_msg_add_delete(secret_state->sam_ldb,
3253 mem_ctx, msg, "currentValue") != LDB_SUCCESS) {
3254 return NT_STATUS_NO_MEMORY;
3258 /* modify the samdb record */
3259 ret = dsdb_replace(secret_state->sam_ldb, msg, 0);
3260 if (ret != LDB_SUCCESS) {
3261 /* we really need samdb.c to return NTSTATUS */
3262 return NT_STATUS_UNSUCCESSFUL;
3265 return NT_STATUS_OK;
3272 static NTSTATUS dcesrv_lsa_QuerySecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3273 struct lsa_QuerySecret *r)
3275 struct dcesrv_handle *h;
3276 struct lsa_secret_state *secret_state;
3277 struct ldb_message *msg;
3278 DATA_BLOB session_key;
3279 DATA_BLOB crypt_secret, secret;
3281 struct ldb_message **res;
3282 const char *attrs[] = {
3292 DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3294 /* Ensure user is permitted to read this... */
3295 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3297 case SECURITY_SYSTEM:
3298 case SECURITY_ADMINISTRATOR:
3301 /* Users and annonymous are not allowed to read secrets */
3302 return NT_STATUS_ACCESS_DENIED;
3305 secret_state = h->data;
3307 /* pull all the user attributes */
3308 ret = gendb_search_dn(secret_state->sam_ldb, mem_ctx,
3309 secret_state->secret_dn, &res, attrs);
3311 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3315 nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
3316 if (!NT_STATUS_IS_OK(nt_status)) {
3320 if (r->in.old_val) {
3321 const struct ldb_val *prior_val;
3322 r->out.old_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3323 if (!r->out.old_val) {
3324 return NT_STATUS_NO_MEMORY;
3326 prior_val = ldb_msg_find_ldb_val(res[0], "priorValue");
3328 if (prior_val && prior_val->length) {
3329 secret.data = prior_val->data;
3330 secret.length = prior_val->length;
3333 crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3334 if (!crypt_secret.length) {
3335 return NT_STATUS_NO_MEMORY;
3337 r->out.old_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3338 if (!r->out.old_val->buf) {
3339 return NT_STATUS_NO_MEMORY;
3341 r->out.old_val->buf->size = crypt_secret.length;
3342 r->out.old_val->buf->length = crypt_secret.length;
3343 r->out.old_val->buf->data = crypt_secret.data;
3347 if (r->in.old_mtime) {
3348 r->out.old_mtime = talloc(mem_ctx, NTTIME);
3349 if (!r->out.old_mtime) {
3350 return NT_STATUS_NO_MEMORY;
3352 *r->out.old_mtime = ldb_msg_find_attr_as_uint64(res[0], "priorSetTime", 0);
3355 if (r->in.new_val) {
3356 const struct ldb_val *new_val;
3357 r->out.new_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3358 if (!r->out.new_val) {
3359 return NT_STATUS_NO_MEMORY;
3362 new_val = ldb_msg_find_ldb_val(res[0], "currentValue");
3364 if (new_val && new_val->length) {
3365 secret.data = new_val->data;
3366 secret.length = new_val->length;
3369 crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3370 if (!crypt_secret.length) {
3371 return NT_STATUS_NO_MEMORY;
3373 r->out.new_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3374 if (!r->out.new_val->buf) {
3375 return NT_STATUS_NO_MEMORY;
3377 r->out.new_val->buf->length = crypt_secret.length;
3378 r->out.new_val->buf->size = crypt_secret.length;
3379 r->out.new_val->buf->data = crypt_secret.data;
3383 if (r->in.new_mtime) {
3384 r->out.new_mtime = talloc(mem_ctx, NTTIME);
3385 if (!r->out.new_mtime) {
3386 return NT_STATUS_NO_MEMORY;
3388 *r->out.new_mtime = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
3391 return NT_STATUS_OK;
3398 static NTSTATUS dcesrv_lsa_LookupPrivValue(struct dcesrv_call_state *dce_call,
3399 TALLOC_CTX *mem_ctx,
3400 struct lsa_LookupPrivValue *r)
3402 struct dcesrv_handle *h;
3403 struct lsa_policy_state *state;
3406 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3410 id = sec_privilege_id(r->in.name->string);
3411 if (id == SEC_PRIV_INVALID) {
3412 return NT_STATUS_NO_SUCH_PRIVILEGE;
3415 r->out.luid->low = id;
3416 r->out.luid->high = 0;
3418 return NT_STATUS_OK;
3425 static NTSTATUS dcesrv_lsa_LookupPrivName(struct dcesrv_call_state *dce_call,
3426 TALLOC_CTX *mem_ctx,
3427 struct lsa_LookupPrivName *r)
3429 struct dcesrv_handle *h;
3430 struct lsa_policy_state *state;
3431 struct lsa_StringLarge *name;
3432 const char *privname;
3434 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3438 if (r->in.luid->high != 0) {
3439 return NT_STATUS_NO_SUCH_PRIVILEGE;
3442 privname = sec_privilege_name(r->in.luid->low);
3443 if (privname == NULL) {
3444 return NT_STATUS_NO_SUCH_PRIVILEGE;
3447 name = talloc(mem_ctx, struct lsa_StringLarge);
3449 return NT_STATUS_NO_MEMORY;
3452 name->string = privname;
3454 *r->out.name = name;
3456 return NT_STATUS_OK;
3461 lsa_LookupPrivDisplayName
3463 static NTSTATUS dcesrv_lsa_LookupPrivDisplayName(struct dcesrv_call_state *dce_call,
3464 TALLOC_CTX *mem_ctx,
3465 struct lsa_LookupPrivDisplayName *r)
3467 struct dcesrv_handle *h;
3468 struct lsa_policy_state *state;
3469 struct lsa_StringLarge *disp_name = NULL;
3470 enum sec_privilege id;
3472 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3476 id = sec_privilege_id(r->in.name->string);
3477 if (id == SEC_PRIV_INVALID) {
3478 return NT_STATUS_NO_SUCH_PRIVILEGE;
3481 disp_name = talloc(mem_ctx, struct lsa_StringLarge);
3482 if (disp_name == NULL) {
3483 return NT_STATUS_NO_MEMORY;
3486 disp_name->string = sec_privilege_display_name(id, &r->in.language_id);
3487 if (disp_name->string == NULL) {
3488 return NT_STATUS_INTERNAL_ERROR;
3491 *r->out.disp_name = disp_name;
3492 *r->out.returned_language_id = 0;
3494 return NT_STATUS_OK;
3499 lsa_EnumAccountsWithUserRight
3501 static NTSTATUS dcesrv_lsa_EnumAccountsWithUserRight(struct dcesrv_call_state *dce_call,
3502 TALLOC_CTX *mem_ctx,
3503 struct lsa_EnumAccountsWithUserRight *r)
3505 struct dcesrv_handle *h;
3506 struct lsa_policy_state *state;
3508 struct ldb_message **res;
3509 const char * const attrs[] = { "objectSid", NULL};
3510 const char *privname;
3512 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3516 if (r->in.name == NULL) {
3517 return NT_STATUS_NO_SUCH_PRIVILEGE;
3520 privname = r->in.name->string;
3521 if (sec_privilege_id(privname) == SEC_PRIV_INVALID && sec_right_bit(privname) == 0) {
3522 return NT_STATUS_NO_SUCH_PRIVILEGE;
3525 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
3526 "privilege=%s", privname);
3528 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3531 return NT_STATUS_NO_MORE_ENTRIES;
3534 r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, ret);
3535 if (r->out.sids->sids == NULL) {
3536 return NT_STATUS_NO_MEMORY;
3538 for (i=0;i<ret;i++) {
3539 r->out.sids->sids[i].sid = samdb_result_dom_sid(r->out.sids->sids,
3540 res[i], "objectSid");
3541 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
3543 r->out.sids->num_sids = ret;
3545 return NT_STATUS_OK;
3550 lsa_AddAccountRights
3552 static NTSTATUS dcesrv_lsa_AddAccountRights(struct dcesrv_call_state *dce_call,
3553 TALLOC_CTX *mem_ctx,
3554 struct lsa_AddAccountRights *r)
3556 struct dcesrv_handle *h;
3557 struct lsa_policy_state *state;
3559 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3563 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3565 r->in.sid, r->in.rights);
3570 lsa_RemoveAccountRights
3572 static NTSTATUS dcesrv_lsa_RemoveAccountRights(struct dcesrv_call_state *dce_call,
3573 TALLOC_CTX *mem_ctx,
3574 struct lsa_RemoveAccountRights *r)
3576 struct dcesrv_handle *h;
3577 struct lsa_policy_state *state;
3579 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3583 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3584 LDB_FLAG_MOD_DELETE,
3585 r->in.sid, r->in.rights);
3590 lsa_StorePrivateData
3592 static NTSTATUS dcesrv_lsa_StorePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3593 struct lsa_StorePrivateData *r)
3595 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3600 lsa_RetrievePrivateData
3602 static NTSTATUS dcesrv_lsa_RetrievePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3603 struct lsa_RetrievePrivateData *r)
3605 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3612 static NTSTATUS dcesrv_lsa_GetUserName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3613 struct lsa_GetUserName *r)
3615 NTSTATUS status = NT_STATUS_OK;
3616 const char *account_name;
3617 const char *authority_name;
3618 struct lsa_String *_account_name;
3619 struct lsa_String *_authority_name = NULL;
3621 /* this is what w2k3 does */
3622 r->out.account_name = r->in.account_name;
3623 r->out.authority_name = r->in.authority_name;
3625 if (r->in.account_name
3626 && *r->in.account_name
3627 /* && *(*r->in.account_name)->string */
3629 return NT_STATUS_INVALID_PARAMETER;
3632 if (r->in.authority_name
3633 && *r->in.authority_name
3634 /* && *(*r->in.authority_name)->string */
3636 return NT_STATUS_INVALID_PARAMETER;
3639 account_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->server_info->account_name);
3640 authority_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->server_info->domain_name);
3642 _account_name = talloc(mem_ctx, struct lsa_String);
3643 NT_STATUS_HAVE_NO_MEMORY(_account_name);
3644 _account_name->string = account_name;
3646 if (r->in.authority_name) {
3647 _authority_name = talloc(mem_ctx, struct lsa_String);
3648 NT_STATUS_HAVE_NO_MEMORY(_authority_name);
3649 _authority_name->string = authority_name;
3652 *r->out.account_name = _account_name;
3653 if (r->out.authority_name) {
3654 *r->out.authority_name = _authority_name;
3663 static NTSTATUS dcesrv_lsa_SetInfoPolicy2(struct dcesrv_call_state *dce_call,
3664 TALLOC_CTX *mem_ctx,
3665 struct lsa_SetInfoPolicy2 *r)
3667 /* need to support these */
3668 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3672 lsa_QueryDomainInformationPolicy
3674 static NTSTATUS dcesrv_lsa_QueryDomainInformationPolicy(struct dcesrv_call_state *dce_call,
3675 TALLOC_CTX *mem_ctx,
3676 struct lsa_QueryDomainInformationPolicy *r)
3678 union lsa_DomainInformationPolicy *info;
3680 info = talloc_zero(r->out.info, union lsa_DomainInformationPolicy);
3682 return NT_STATUS_NO_MEMORY;
3685 switch (r->in.level) {
3686 case LSA_DOMAIN_INFO_POLICY_EFS:
3688 *r->out.info = NULL;
3689 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3690 case LSA_DOMAIN_INFO_POLICY_KERBEROS:
3692 struct lsa_DomainInfoKerberos *k = &info->kerberos_info;
3693 struct smb_krb5_context *smb_krb5_context;
3694 int ret = smb_krb5_init_context(mem_ctx,
3695 dce_call->event_ctx,
3696 dce_call->conn->dce_ctx->lp_ctx,
3700 *r->out.info = NULL;
3701 return NT_STATUS_INTERNAL_ERROR;
3703 k->enforce_restrictions = 0; /* FIXME, details missing from MS-LSAD 2.2.53 */
3704 k->service_tkt_lifetime = 0; /* Need to find somewhere to store this, and query in KDC too */
3705 k->user_tkt_lifetime = 0; /* Need to find somewhere to store this, and query in KDC too */
3706 k->user_tkt_renewaltime = 0; /* Need to find somewhere to store this, and query in KDC too */
3707 k->clock_skew = krb5_get_max_time_skew(smb_krb5_context->krb5_context);
3709 talloc_free(smb_krb5_context);
3710 *r->out.info = info;
3711 return NT_STATUS_OK;
3715 *r->out.info = NULL;
3716 return NT_STATUS_INVALID_INFO_CLASS;
3721 lsa_SetDomInfoPolicy
3723 static NTSTATUS dcesrv_lsa_SetDomainInformationPolicy(struct dcesrv_call_state *dce_call,
3724 TALLOC_CTX *mem_ctx,
3725 struct lsa_SetDomainInformationPolicy *r)
3727 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3733 static NTSTATUS dcesrv_lsa_TestCall(struct dcesrv_call_state *dce_call,
3734 TALLOC_CTX *mem_ctx,
3735 struct lsa_TestCall *r)
3737 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3743 static NTSTATUS dcesrv_lsa_CREDRWRITE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3744 struct lsa_CREDRWRITE *r)
3746 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3753 static NTSTATUS dcesrv_lsa_CREDRREAD(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3754 struct lsa_CREDRREAD *r)
3756 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3763 static NTSTATUS dcesrv_lsa_CREDRENUMERATE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3764 struct lsa_CREDRENUMERATE *r)
3766 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3771 lsa_CREDRWRITEDOMAINCREDENTIALS
3773 static NTSTATUS dcesrv_lsa_CREDRWRITEDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3774 struct lsa_CREDRWRITEDOMAINCREDENTIALS *r)
3776 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3781 lsa_CREDRREADDOMAINCREDENTIALS
3783 static NTSTATUS dcesrv_lsa_CREDRREADDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3784 struct lsa_CREDRREADDOMAINCREDENTIALS *r)
3786 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3793 static NTSTATUS dcesrv_lsa_CREDRDELETE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3794 struct lsa_CREDRDELETE *r)
3796 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3801 lsa_CREDRGETTARGETINFO
3803 static NTSTATUS dcesrv_lsa_CREDRGETTARGETINFO(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3804 struct lsa_CREDRGETTARGETINFO *r)
3806 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3811 lsa_CREDRPROFILELOADED
3813 static NTSTATUS dcesrv_lsa_CREDRPROFILELOADED(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3814 struct lsa_CREDRPROFILELOADED *r)
3816 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3821 lsa_CREDRGETSESSIONTYPES
3823 static NTSTATUS dcesrv_lsa_CREDRGETSESSIONTYPES(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3824 struct lsa_CREDRGETSESSIONTYPES *r)
3826 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3831 lsa_LSARREGISTERAUDITEVENT
3833 static NTSTATUS dcesrv_lsa_LSARREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3834 struct lsa_LSARREGISTERAUDITEVENT *r)
3836 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3841 lsa_LSARGENAUDITEVENT
3843 static NTSTATUS dcesrv_lsa_LSARGENAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3844 struct lsa_LSARGENAUDITEVENT *r)
3846 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3851 lsa_LSARUNREGISTERAUDITEVENT
3853 static NTSTATUS dcesrv_lsa_LSARUNREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3854 struct lsa_LSARUNREGISTERAUDITEVENT *r)
3856 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3861 lsa_lsaRQueryForestTrustInformation
3863 static NTSTATUS dcesrv_lsa_lsaRQueryForestTrustInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3864 struct lsa_lsaRQueryForestTrustInformation *r)
3866 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3869 #define DNS_CMP_MATCH 0
3870 #define DNS_CMP_FIRST_IS_CHILD 1
3871 #define DNS_CMP_SECOND_IS_CHILD 2
3872 #define DNS_CMP_NO_MATCH 3
3874 /* this function assumes names are well formed DNS names.
3875 * it doesn't validate them */
3876 static int dns_cmp(const char *s1, size_t l1,
3877 const char *s2, size_t l2)
3879 const char *p1, *p2;
3884 if (strcasecmp_m(s1, s2) == 0) {
3885 return DNS_CMP_MATCH;
3887 return DNS_CMP_NO_MATCH;
3895 cret = DNS_CMP_FIRST_IS_CHILD;
3901 cret = DNS_CMP_SECOND_IS_CHILD;
3904 if (p1[t1 - t2 - 1] != '.') {
3905 return DNS_CMP_NO_MATCH;
3908 if (strcasecmp_m(&p1[t1 - t2], p2) == 0) {
3912 return DNS_CMP_NO_MATCH;
3915 /* decode all TDOs forest trust info blobs */
3916 static NTSTATUS get_ft_info(TALLOC_CTX *mem_ctx,
3917 struct ldb_message *msg,
3918 struct ForestTrustInfo *info)
3920 const struct ldb_val *ft_blob;
3921 enum ndr_err_code ndr_err;
3923 ft_blob = ldb_msg_find_ldb_val(msg, "msDS-TrustForestTrustInfo");
3924 if (!ft_blob || !ft_blob->data) {
3925 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3927 /* ldb_val is equivalent to DATA_BLOB */
3928 ndr_err = ndr_pull_struct_blob_all(ft_blob, mem_ctx, info,
3929 (ndr_pull_flags_fn_t)ndr_pull_ForestTrustInfo);
3930 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
3931 return NT_STATUS_INVALID_DOMAIN_STATE;
3934 return NT_STATUS_OK;
3937 static NTSTATUS own_ft_info(struct lsa_policy_state *ps,
3938 struct ForestTrustInfo *fti)
3940 struct ForestTrustDataDomainInfo *info;
3941 struct ForestTrustInfoRecord *rec;
3945 fti->records = talloc_array(fti,
3946 struct ForestTrustInfoRecordArmor, 2);
3947 if (!fti->records) {
3948 return NT_STATUS_NO_MEMORY;
3952 rec = &fti->records[0].record;
3956 rec->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
3958 rec->data.name.string = talloc_strdup(fti, ps->forest_dns);
3959 if (!rec->data.name.string) {
3960 return NT_STATUS_NO_MEMORY;
3962 rec->data.name.size = strlen(rec->data.name.string);
3965 rec = &fti->records[1].record;
3969 rec->type = LSA_FOREST_TRUST_DOMAIN_INFO;
3971 info = &rec->data.info;
3973 info->sid = *ps->domain_sid;
3974 info->dns_name.string = talloc_strdup(fti, ps->domain_dns);
3975 if (!info->dns_name.string) {
3976 return NT_STATUS_NO_MEMORY;
3978 info->dns_name.size = strlen(info->dns_name.string);
3979 info->netbios_name.string = talloc_strdup(fti, ps->domain_name);
3980 if (!info->netbios_name.string) {
3981 return NT_STATUS_NO_MEMORY;
3983 info->netbios_name.size = strlen(info->netbios_name.string);
3985 return NT_STATUS_OK;
3988 static NTSTATUS make_ft_info(TALLOC_CTX *mem_ctx,
3989 struct lsa_ForestTrustInformation *lfti,
3990 struct ForestTrustInfo *fti)
3992 struct lsa_ForestTrustRecord *lrec;
3993 struct ForestTrustInfoRecord *rec;
3994 struct lsa_StringLarge *tln;
3995 struct lsa_ForestTrustDomainInfo *info;
3999 fti->count = lfti->count;
4000 fti->records = talloc_array(mem_ctx,
4001 struct ForestTrustInfoRecordArmor,
4003 if (!fti->records) {
4004 return NT_STATUS_NO_MEMORY;
4006 for (i = 0; i < fti->count; i++) {
4007 lrec = lfti->entries[i];
4008 rec = &fti->records[i].record;
4010 rec->flags = lrec->flags;
4011 rec->timestamp = lrec->time;
4012 rec->type = lrec->type;
4014 switch (lrec->type) {
4015 case LSA_FOREST_TRUST_TOP_LEVEL_NAME:
4016 case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
4017 tln = &lrec->forest_trust_data.top_level_name;
4018 rec->data.name.string =
4019 talloc_strdup(mem_ctx, tln->string);
4020 if (!rec->data.name.string) {
4021 return NT_STATUS_NO_MEMORY;
4023 rec->data.name.size = strlen(rec->data.name.string);
4025 case LSA_FOREST_TRUST_DOMAIN_INFO:
4026 info = &lrec->forest_trust_data.domain_info;
4027 rec->data.info.sid = *info->domain_sid;
4028 rec->data.info.dns_name.string =
4029 talloc_strdup(mem_ctx,
4030 info->dns_domain_name.string);
4031 if (!rec->data.info.dns_name.string) {
4032 return NT_STATUS_NO_MEMORY;
4034 rec->data.info.dns_name.size =
4035 strlen(rec->data.info.dns_name.string);
4036 rec->data.info.netbios_name.string =
4037 talloc_strdup(mem_ctx,
4038 info->netbios_domain_name.string);
4039 if (!rec->data.info.netbios_name.string) {
4040 return NT_STATUS_NO_MEMORY;
4042 rec->data.info.netbios_name.size =
4043 strlen(rec->data.info.netbios_name.string);
4046 return NT_STATUS_INVALID_DOMAIN_STATE;
4050 return NT_STATUS_OK;
4053 static NTSTATUS add_collision(struct lsa_ForestTrustCollisionInfo *c_info,
4054 uint32_t index, uint32_t collision_type,
4055 uint32_t conflict_type, const char *tdo_name);
4057 static NTSTATUS check_ft_info(TALLOC_CTX *mem_ctx,
4058 const char *tdo_name,
4059 struct ForestTrustInfo *tdo_fti,
4060 struct ForestTrustInfo *new_fti,
4061 struct lsa_ForestTrustCollisionInfo *c_info)
4063 struct ForestTrustInfoRecord *nrec;
4064 struct ForestTrustInfoRecord *trec;
4065 const char *dns_name;
4066 const char *nb_name;
4067 struct dom_sid *sid;
4073 uint32_t new_fti_idx;
4075 /* use always TDO type, until we understand when Xref can be used */
4076 uint32_t collision_type = LSA_FOREST_TRUST_COLLISION_TDO;
4084 for (new_fti_idx = 0; new_fti_idx < new_fti->count; new_fti_idx++) {
4086 nrec = &new_fti->records[new_fti_idx].record;
4088 tln_conflict = false;
4089 sid_conflict = false;
4090 nb_conflict = false;
4093 switch (nrec->type) {
4094 case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
4095 /* exclusions do not conflict by definition */
4098 case FOREST_TRUST_TOP_LEVEL_NAME:
4099 dns_name = nrec->data.name.string;
4100 dns_len = nrec->data.name.size;
4103 case LSA_FOREST_TRUST_DOMAIN_INFO:
4104 dns_name = nrec->data.info.dns_name.string;
4105 dns_len = nrec->data.info.dns_name.size;
4106 nb_name = nrec->data.info.netbios_name.string;
4107 nb_len = nrec->data.info.netbios_name.size;
4108 sid = &nrec->data.info.sid;
4112 if (!dns_name) continue;
4114 /* check if this is already taken and not excluded */
4115 for (i = 0; i < tdo_fti->count; i++) {
4116 trec = &tdo_fti->records[i].record;
4118 switch (trec->type) {
4119 case FOREST_TRUST_TOP_LEVEL_NAME:
4121 tname = trec->data.name.string;
4122 tlen = trec->data.name.size;
4124 case FOREST_TRUST_TOP_LEVEL_NAME_EX:
4126 tname = trec->data.name.string;
4127 tlen = trec->data.name.size;
4129 case FOREST_TRUST_DOMAIN_INFO:
4131 tname = trec->data.info.dns_name.string;
4132 tlen = trec->data.info.dns_name.size;
4134 ret = dns_cmp(dns_name, dns_len, tname, tlen);
4137 /* if it matches exclusion,
4138 * it doesn't conflict */
4144 case DNS_CMP_FIRST_IS_CHILD:
4145 case DNS_CMP_SECOND_IS_CHILD:
4146 tln_conflict = true;
4152 /* explicit exclusion, no dns name conflict here */
4154 tln_conflict = false;
4157 if (trec->type != FOREST_TRUST_DOMAIN_INFO) {
4161 /* also test for domain info */
4162 if (!(trec->flags & LSA_SID_DISABLED_ADMIN) &&
4163 dom_sid_compare(&trec->data.info.sid, sid) == 0) {
4164 sid_conflict = true;
4166 if (!(trec->flags & LSA_NB_DISABLED_ADMIN) &&
4167 strcasecmp_m(trec->data.info.netbios_name.string,
4174 nt_status = add_collision(c_info, new_fti_idx,
4176 LSA_TLN_DISABLED_CONFLICT,
4180 nt_status = add_collision(c_info, new_fti_idx,
4182 LSA_SID_DISABLED_CONFLICT,
4186 nt_status = add_collision(c_info, new_fti_idx,
4188 LSA_NB_DISABLED_CONFLICT,
4193 return NT_STATUS_OK;
4196 static NTSTATUS add_collision(struct lsa_ForestTrustCollisionInfo *c_info,
4197 uint32_t idx, uint32_t collision_type,
4198 uint32_t conflict_type, const char *tdo_name)
4200 struct lsa_ForestTrustCollisionRecord **es;
4201 uint32_t i = c_info->count;
4203 es = talloc_realloc(c_info, c_info->entries,
4204 struct lsa_ForestTrustCollisionRecord *, i + 1);
4206 return NT_STATUS_NO_MEMORY;
4208 c_info->entries = es;
4209 c_info->count = i + 1;
4211 es[i] = talloc(es, struct lsa_ForestTrustCollisionRecord);
4213 return NT_STATUS_NO_MEMORY;
4217 es[i]->type = collision_type;
4218 es[i]->flags.flags = conflict_type;
4219 es[i]->name.string = talloc_strdup(es[i], tdo_name);
4220 if (!es[i]->name.string) {
4221 return NT_STATUS_NO_MEMORY;
4223 es[i]->name.size = strlen(es[i]->name.string);
4225 return NT_STATUS_OK;
4229 lsa_lsaRSetForestTrustInformation
4231 static NTSTATUS dcesrv_lsa_lsaRSetForestTrustInformation(struct dcesrv_call_state *dce_call,
4232 TALLOC_CTX *mem_ctx,
4233 struct lsa_lsaRSetForestTrustInformation *r)
4235 struct dcesrv_handle *h;
4236 struct lsa_policy_state *p_state;
4237 const char *trust_attrs[] = { "trustPartner", "trustAttributes",
4238 "msDS-TrustForestTrustInfo", NULL };
4239 struct ldb_message **dom_res = NULL;
4240 struct ldb_dn *tdo_dn;
4241 struct ldb_message *msg;
4243 const char *td_name;
4244 uint32_t trust_attributes;
4245 struct lsa_ForestTrustCollisionInfo *c_info;
4246 struct ForestTrustInfo *nfti;
4247 struct ForestTrustInfo *fti;
4249 enum ndr_err_code ndr_err;
4254 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
4258 if (strcmp(p_state->domain_dns, p_state->forest_dns)) {
4259 return NT_STATUS_INVALID_DOMAIN_STATE;
4262 /* abort if we are not a PDC */
4263 if (!samdb_is_pdc(p_state->sam_ldb)) {
4264 return NT_STATUS_INVALID_DOMAIN_ROLE;
4267 ret = samdb_rodc(p_state->sam_ldb, &am_rodc);
4268 if (ret == LDB_SUCCESS && am_rodc) {
4269 return NT_STATUS_NO_SUCH_DOMAIN;
4272 /* check caller has TRUSTED_SET_AUTH */
4274 /* fetch all trusted domain objects */
4275 num_res = gendb_search(p_state->sam_ldb, mem_ctx,
4277 &dom_res, trust_attrs,
4278 "(objectclass=trustedDomain)");
4280 return NT_STATUS_NO_SUCH_DOMAIN;
4283 for (i = 0; i < num_res; i++) {
4284 td_name = ldb_msg_find_attr_as_string(dom_res[i],
4285 "trustPartner", NULL);
4287 return NT_STATUS_INVALID_DOMAIN_STATE;
4289 if (strcasecmp_m(td_name,
4290 r->in.trusted_domain_name->string) == 0) {
4295 return NT_STATUS_NO_SUCH_DOMAIN;
4298 tdo_dn = dom_res[i]->dn;
4300 trust_attributes = ldb_msg_find_attr_as_uint(dom_res[i],
4301 "trustAttributes", 0);
4302 if (!(trust_attributes & NETR_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
4303 return NT_STATUS_INVALID_PARAMETER;
4306 if (r->in.highest_record_type >= LSA_FOREST_TRUST_RECORD_TYPE_LAST) {
4307 return NT_STATUS_INVALID_PARAMETER;
4310 nfti = talloc(mem_ctx, struct ForestTrustInfo);
4312 return NT_STATUS_NO_MEMORY;
4315 nt_status = make_ft_info(nfti, r->in.forest_trust_info, nfti);
4316 if (!NT_STATUS_IS_OK(nt_status)) {
4320 c_info = talloc_zero(r->out.collision_info,
4321 struct lsa_ForestTrustCollisionInfo);
4323 return NT_STATUS_NO_MEMORY;
4326 /* first check own info, then other domains */
4327 fti = talloc(mem_ctx, struct ForestTrustInfo);
4329 return NT_STATUS_NO_MEMORY;
4332 nt_status = own_ft_info(p_state, fti);
4333 if (!NT_STATUS_IS_OK(nt_status)) {
4337 nt_status = check_ft_info(c_info, p_state->domain_dns,
4339 if (!NT_STATUS_IS_OK(nt_status)) {
4343 for (i = 0; i < num_res; i++) {
4344 fti = talloc(mem_ctx, struct ForestTrustInfo);
4346 return NT_STATUS_NO_MEMORY;
4349 nt_status = get_ft_info(mem_ctx, dom_res[i], fti);
4350 if (!NT_STATUS_IS_OK(nt_status)) {
4351 if (NT_STATUS_EQUAL(nt_status,
4352 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4358 td_name = ldb_msg_find_attr_as_string(dom_res[i],
4359 "trustPartner", NULL);
4361 return NT_STATUS_INVALID_DOMAIN_STATE;
4364 nt_status = check_ft_info(c_info, td_name, fti, nfti, c_info);
4365 if (!NT_STATUS_IS_OK(nt_status)) {
4370 *r->out.collision_info = c_info;
4372 if (r->in.check_only != 0) {
4373 return NT_STATUS_OK;
4376 /* not just a check, write info back */
4378 ndr_err = ndr_push_struct_blob(&ft_blob, mem_ctx, nfti,
4379 (ndr_push_flags_fn_t)ndr_push_ForestTrustInfo);
4380 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
4381 return NT_STATUS_INVALID_PARAMETER;
4384 msg = ldb_msg_new(mem_ctx);
4386 return NT_STATUS_NO_MEMORY;
4389 msg->dn = ldb_dn_copy(mem_ctx, tdo_dn);
4391 return NT_STATUS_NO_MEMORY;
4394 ret = ldb_msg_add_empty(msg, "msDS-TrustForestTrustInfo",
4395 LDB_FLAG_MOD_REPLACE, NULL);
4396 if (ret != LDB_SUCCESS) {
4397 return NT_STATUS_NO_MEMORY;
4399 ret = ldb_msg_add_value(msg, "msDS-TrustForestTrustInfo",
4401 if (ret != LDB_SUCCESS) {
4402 return NT_STATUS_NO_MEMORY;
4405 ret = ldb_modify(p_state->sam_ldb, msg);
4406 if (ret != LDB_SUCCESS) {
4407 DEBUG(0, ("Failed to store Forest Trust Info: %s\n",
4408 ldb_errstring(p_state->sam_ldb)));
4411 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
4412 return NT_STATUS_ACCESS_DENIED;
4414 return NT_STATUS_INTERNAL_DB_CORRUPTION;
4418 return NT_STATUS_OK;
4424 static NTSTATUS dcesrv_lsa_CREDRRENAME(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4425 struct lsa_CREDRRENAME *r)
4427 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4433 lsa_LSAROPENPOLICYSCE
4435 static NTSTATUS dcesrv_lsa_LSAROPENPOLICYSCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4436 struct lsa_LSAROPENPOLICYSCE *r)
4438 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4443 lsa_LSARADTREGISTERSECURITYEVENTSOURCE
4445 static NTSTATUS dcesrv_lsa_LSARADTREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4446 struct lsa_LSARADTREGISTERSECURITYEVENTSOURCE *r)
4448 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4453 lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE
4455 static NTSTATUS dcesrv_lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4456 struct lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE *r)
4458 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4463 lsa_LSARADTREPORTSECURITYEVENT
4465 static NTSTATUS dcesrv_lsa_LSARADTREPORTSECURITYEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4466 struct lsa_LSARADTREPORTSECURITYEVENT *r)
4468 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4472 /* include the generated boilerplate */
4473 #include "librpc/gen_ndr/ndr_lsa_s.c"
4477 /*****************************************
4478 NOTE! The remaining calls below were
4479 removed in w2k3, so the DCESRV_FAULT()
4480 replies are the correct implementation. Do
4481 not try and fill these in with anything else
4482 ******************************************/
4485 dssetup_DsRoleDnsNameToFlatName
4487 static WERROR dcesrv_dssetup_DsRoleDnsNameToFlatName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4488 struct dssetup_DsRoleDnsNameToFlatName *r)
4490 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4495 dssetup_DsRoleDcAsDc
4497 static WERROR dcesrv_dssetup_DsRoleDcAsDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4498 struct dssetup_DsRoleDcAsDc *r)
4500 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4505 dssetup_DsRoleDcAsReplica
4507 static WERROR dcesrv_dssetup_DsRoleDcAsReplica(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4508 struct dssetup_DsRoleDcAsReplica *r)
4510 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4515 dssetup_DsRoleDemoteDc
4517 static WERROR dcesrv_dssetup_DsRoleDemoteDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4518 struct dssetup_DsRoleDemoteDc *r)
4520 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4525 dssetup_DsRoleGetDcOperationProgress
4527 static WERROR dcesrv_dssetup_DsRoleGetDcOperationProgress(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4528 struct dssetup_DsRoleGetDcOperationProgress *r)
4530 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4535 dssetup_DsRoleGetDcOperationResults
4537 static WERROR dcesrv_dssetup_DsRoleGetDcOperationResults(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4538 struct dssetup_DsRoleGetDcOperationResults *r)
4540 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4545 dssetup_DsRoleCancel
4547 static WERROR dcesrv_dssetup_DsRoleCancel(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4548 struct dssetup_DsRoleCancel *r)
4550 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4555 dssetup_DsRoleServerSaveStateForUpgrade
4557 static WERROR dcesrv_dssetup_DsRoleServerSaveStateForUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4558 struct dssetup_DsRoleServerSaveStateForUpgrade *r)
4560 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4565 dssetup_DsRoleUpgradeDownlevelServer
4567 static WERROR dcesrv_dssetup_DsRoleUpgradeDownlevelServer(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4568 struct dssetup_DsRoleUpgradeDownlevelServer *r)
4570 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4575 dssetup_DsRoleAbortDownlevelServerUpgrade
4577 static WERROR dcesrv_dssetup_DsRoleAbortDownlevelServerUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4578 struct dssetup_DsRoleAbortDownlevelServerUpgrade *r)
4580 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4584 /* include the generated boilerplate */
4585 #include "librpc/gen_ndr/ndr_dssetup_s.c"
4587 NTSTATUS dcerpc_server_lsa_init(void)
4591 ret = dcerpc_server_dssetup_init();
4592 if (!NT_STATUS_IS_OK(ret)) {
4595 ret = dcerpc_server_lsarpc_init();
4596 if (!NT_STATUS_IS_OK(ret)) {