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"
34 this type allows us to distinguish handle types
38 state associated with a lsa_OpenAccount() operation
40 struct lsa_account_state {
41 struct lsa_policy_state *policy;
43 struct dom_sid *account_sid;
48 state associated with a lsa_OpenSecret() operation
50 struct lsa_secret_state {
51 struct lsa_policy_state *policy;
53 struct ldb_dn *secret_dn;
54 struct ldb_context *sam_ldb;
59 state associated with a lsa_OpenTrustedDomain() operation
61 struct lsa_trusted_domain_state {
62 struct lsa_policy_state *policy;
64 struct ldb_dn *trusted_domain_dn;
65 struct ldb_dn *trusted_domain_user_dn;
69 this is based on the samba3 function make_lsa_object_sd()
70 It uses the same logic, but with samba4 helper functions
72 static NTSTATUS dcesrv_build_lsa_sd(TALLOC_CTX *mem_ctx,
73 struct security_descriptor **sd,
79 struct dom_sid *domain_sid, *domain_admins_sid;
80 const char *domain_admins_sid_str, *sidstr;
81 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
83 status = dom_sid_split_rid(tmp_ctx, sid, &domain_sid, &rid);
84 NT_STATUS_NOT_OK_RETURN_AND_FREE(status, tmp_ctx);
86 domain_admins_sid = dom_sid_add_rid(tmp_ctx, domain_sid, DOMAIN_RID_ADMINS);
87 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(domain_admins_sid, tmp_ctx);
89 domain_admins_sid_str = dom_sid_string(tmp_ctx, domain_admins_sid);
90 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(domain_admins_sid_str, tmp_ctx);
92 sidstr = dom_sid_string(tmp_ctx, sid);
93 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sidstr, tmp_ctx);
95 *sd = security_descriptor_dacl_create(mem_ctx,
99 SEC_ACE_TYPE_ACCESS_ALLOWED,
100 SEC_GENERIC_EXECUTE | SEC_GENERIC_READ, 0,
102 SID_BUILTIN_ADMINISTRATORS,
103 SEC_ACE_TYPE_ACCESS_ALLOWED,
106 SID_BUILTIN_ACCOUNT_OPERATORS,
107 SEC_ACE_TYPE_ACCESS_ALLOWED,
110 domain_admins_sid_str,
111 SEC_ACE_TYPE_ACCESS_ALLOWED,
115 SEC_ACE_TYPE_ACCESS_ALLOWED,
119 talloc_free(tmp_ctx);
121 NT_STATUS_HAVE_NO_MEMORY(*sd);
127 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call,
129 struct lsa_EnumAccountRights *r);
131 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
133 struct lsa_policy_state *state,
136 const struct lsa_RightSet *rights);
141 static NTSTATUS dcesrv_lsa_Close(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
144 struct dcesrv_handle *h;
146 *r->out.handle = *r->in.handle;
148 DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
152 ZERO_STRUCTP(r->out.handle);
161 static NTSTATUS dcesrv_lsa_Delete(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
162 struct lsa_Delete *r)
164 return NT_STATUS_NOT_SUPPORTED;
171 static NTSTATUS dcesrv_lsa_DeleteObject(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
172 struct lsa_DeleteObject *r)
174 struct dcesrv_handle *h;
177 DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
179 if (h->wire_handle.handle_type == LSA_HANDLE_SECRET) {
180 struct lsa_secret_state *secret_state = h->data;
182 /* Ensure user is permitted to delete this... */
183 switch (security_session_user_level(dce_call->conn->auth_state.session_info))
185 case SECURITY_SYSTEM:
186 case SECURITY_ADMINISTRATOR:
189 /* Users and annonymous are not allowed delete things */
190 return NT_STATUS_ACCESS_DENIED;
193 ret = ldb_delete(secret_state->sam_ldb,
194 secret_state->secret_dn);
196 if (ret != LDB_SUCCESS) {
197 return NT_STATUS_INVALID_HANDLE;
200 ZERO_STRUCTP(r->out.handle);
203 } else if (h->wire_handle.handle_type == LSA_HANDLE_TRUSTED_DOMAIN) {
204 struct lsa_trusted_domain_state *trusted_domain_state =
205 talloc_get_type(h->data, struct lsa_trusted_domain_state);
206 ret = ldb_transaction_start(trusted_domain_state->policy->sam_ldb);
207 if (ret != LDB_SUCCESS) {
208 return NT_STATUS_INTERNAL_DB_CORRUPTION;
211 ret = ldb_delete(trusted_domain_state->policy->sam_ldb,
212 trusted_domain_state->trusted_domain_dn);
213 if (ret != LDB_SUCCESS) {
214 ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
215 return NT_STATUS_INVALID_HANDLE;
218 if (trusted_domain_state->trusted_domain_user_dn) {
219 ret = ldb_delete(trusted_domain_state->policy->sam_ldb,
220 trusted_domain_state->trusted_domain_user_dn);
221 if (ret != LDB_SUCCESS) {
222 ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
223 return NT_STATUS_INVALID_HANDLE;
227 ret = ldb_transaction_commit(trusted_domain_state->policy->sam_ldb);
228 if (ret != LDB_SUCCESS) {
229 return NT_STATUS_INTERNAL_DB_CORRUPTION;
232 ZERO_STRUCTP(r->out.handle);
235 } else if (h->wire_handle.handle_type == LSA_HANDLE_ACCOUNT) {
236 struct lsa_RightSet *rights;
237 struct lsa_account_state *astate;
238 struct lsa_EnumAccountRights r2;
241 rights = talloc(mem_ctx, struct lsa_RightSet);
243 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
247 r2.in.handle = &astate->policy->handle->wire_handle;
248 r2.in.sid = astate->account_sid;
249 r2.out.rights = rights;
251 /* dcesrv_lsa_EnumAccountRights takes a LSA_HANDLE_POLICY,
252 but we have a LSA_HANDLE_ACCOUNT here, so this call
254 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
255 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
259 if (!NT_STATUS_IS_OK(status)) {
263 status = dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
264 LDB_FLAG_MOD_DELETE, astate->account_sid,
266 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
270 if (!NT_STATUS_IS_OK(status)) {
274 ZERO_STRUCTP(r->out.handle);
277 return NT_STATUS_INVALID_HANDLE;
284 static NTSTATUS dcesrv_lsa_EnumPrivs(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
285 struct lsa_EnumPrivs *r)
287 struct dcesrv_handle *h;
288 struct lsa_policy_state *state;
290 const char *privname;
292 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
296 i = *r->in.resume_handle;
299 while ((privname = sec_privilege_name(i)) &&
300 r->out.privs->count < r->in.max_count) {
301 struct lsa_PrivEntry *e;
303 r->out.privs->privs = talloc_realloc(r->out.privs,
305 struct lsa_PrivEntry,
306 r->out.privs->count+1);
307 if (r->out.privs->privs == NULL) {
308 return NT_STATUS_NO_MEMORY;
310 e = &r->out.privs->privs[r->out.privs->count];
313 e->name.string = privname;
314 r->out.privs->count++;
318 *r->out.resume_handle = i;
327 static NTSTATUS dcesrv_lsa_QuerySecurity(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
328 struct lsa_QuerySecurity *r)
330 struct dcesrv_handle *h;
331 struct security_descriptor *sd;
335 DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
337 sid = dce_call->conn->auth_state.session_info->security_token->user_sid;
339 if (h->wire_handle.handle_type == LSA_HANDLE_POLICY) {
340 status = dcesrv_build_lsa_sd(mem_ctx, &sd, sid, 0);
341 } else if (h->wire_handle.handle_type == LSA_HANDLE_ACCOUNT) {
342 status = dcesrv_build_lsa_sd(mem_ctx, &sd, sid,
343 LSA_ACCOUNT_ALL_ACCESS);
345 return NT_STATUS_INVALID_HANDLE;
347 NT_STATUS_NOT_OK_RETURN(status);
349 (*r->out.sdbuf) = talloc(mem_ctx, struct sec_desc_buf);
350 NT_STATUS_HAVE_NO_MEMORY(*r->out.sdbuf);
352 (*r->out.sdbuf)->sd = sd;
361 static NTSTATUS dcesrv_lsa_SetSecObj(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
362 struct lsa_SetSecObj *r)
364 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
371 static NTSTATUS dcesrv_lsa_ChangePassword(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
372 struct lsa_ChangePassword *r)
374 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
378 dssetup_DsRoleGetPrimaryDomainInformation
380 This is not an LSA call, but is the only call left on the DSSETUP
381 pipe (after the pipe was truncated), and needs lsa_get_policy_state
383 static WERROR dcesrv_dssetup_DsRoleGetPrimaryDomainInformation(struct dcesrv_call_state *dce_call,
385 struct dssetup_DsRoleGetPrimaryDomainInformation *r)
387 union dssetup_DsRoleInfo *info;
389 info = talloc(mem_ctx, union dssetup_DsRoleInfo);
390 W_ERROR_HAVE_NO_MEMORY(info);
392 switch (r->in.level) {
393 case DS_ROLE_BASIC_INFORMATION:
395 enum dssetup_DsRole role = DS_ROLE_STANDALONE_SERVER;
397 const char *domain = NULL;
398 const char *dns_domain = NULL;
399 const char *forest = NULL;
400 struct GUID domain_guid;
401 struct lsa_policy_state *state;
403 NTSTATUS status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx, &state);
404 if (!NT_STATUS_IS_OK(status)) {
405 return ntstatus_to_werror(status);
408 ZERO_STRUCT(domain_guid);
410 switch (lp_server_role(dce_call->conn->dce_ctx->lp_ctx)) {
411 case ROLE_STANDALONE:
412 role = DS_ROLE_STANDALONE_SERVER;
414 case ROLE_DOMAIN_MEMBER:
415 role = DS_ROLE_MEMBER_SERVER;
417 case ROLE_DOMAIN_CONTROLLER:
418 if (samdb_is_pdc(state->sam_ldb)) {
419 role = DS_ROLE_PRIMARY_DC;
421 role = DS_ROLE_BACKUP_DC;
426 switch (lp_server_role(dce_call->conn->dce_ctx->lp_ctx)) {
427 case ROLE_STANDALONE:
428 domain = talloc_strdup(mem_ctx, lp_workgroup(dce_call->conn->dce_ctx->lp_ctx));
429 W_ERROR_HAVE_NO_MEMORY(domain);
431 case ROLE_DOMAIN_MEMBER:
432 domain = talloc_strdup(mem_ctx, lp_workgroup(dce_call->conn->dce_ctx->lp_ctx));
433 W_ERROR_HAVE_NO_MEMORY(domain);
434 /* TODO: what is with dns_domain and forest and guid? */
436 case ROLE_DOMAIN_CONTROLLER:
437 flags = DS_ROLE_PRIMARY_DS_RUNNING;
439 if (state->mixed_domain == 1) {
440 flags |= DS_ROLE_PRIMARY_DS_MIXED_MODE;
443 domain = state->domain_name;
444 dns_domain = state->domain_dns;
445 forest = state->forest_dns;
447 domain_guid = state->domain_guid;
448 flags |= DS_ROLE_PRIMARY_DOMAIN_GUID_PRESENT;
452 info->basic.role = role;
453 info->basic.flags = flags;
454 info->basic.domain = domain;
455 info->basic.dns_domain = dns_domain;
456 info->basic.forest = forest;
457 info->basic.domain_guid = domain_guid;
462 case DS_ROLE_UPGRADE_STATUS:
464 info->upgrade.upgrading = DS_ROLE_NOT_UPGRADING;
465 info->upgrade.previous_role = DS_ROLE_PREVIOUS_UNKNOWN;
470 case DS_ROLE_OP_STATUS:
472 info->opstatus.status = DS_ROLE_OP_IDLE;
478 return WERR_INVALID_PARAM;
481 return WERR_INVALID_PARAM;
485 fill in the AccountDomain info
487 static NTSTATUS dcesrv_lsa_info_AccountDomain(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
488 struct lsa_DomainInfo *info)
490 info->name.string = state->domain_name;
491 info->sid = state->domain_sid;
497 fill in the DNS domain info
499 static NTSTATUS dcesrv_lsa_info_DNS(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
500 struct lsa_DnsDomainInfo *info)
502 info->name.string = state->domain_name;
503 info->sid = state->domain_sid;
504 info->dns_domain.string = state->domain_dns;
505 info->dns_forest.string = state->forest_dns;
506 info->domain_guid = state->domain_guid;
514 static NTSTATUS dcesrv_lsa_QueryInfoPolicy2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
515 struct lsa_QueryInfoPolicy2 *r)
517 struct lsa_policy_state *state;
518 struct dcesrv_handle *h;
519 union lsa_PolicyInformation *info;
523 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
527 info = talloc_zero(mem_ctx, union lsa_PolicyInformation);
529 return NT_STATUS_NO_MEMORY;
533 switch (r->in.level) {
534 case LSA_POLICY_INFO_AUDIT_LOG:
535 /* we don't need to fill in any of this */
536 ZERO_STRUCT(info->audit_log);
538 case LSA_POLICY_INFO_AUDIT_EVENTS:
539 /* we don't need to fill in any of this */
540 ZERO_STRUCT(info->audit_events);
542 case LSA_POLICY_INFO_PD:
543 /* we don't need to fill in any of this */
544 ZERO_STRUCT(info->pd);
547 case LSA_POLICY_INFO_DOMAIN:
548 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->domain);
549 case LSA_POLICY_INFO_ACCOUNT_DOMAIN:
550 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->account_domain);
551 case LSA_POLICY_INFO_L_ACCOUNT_DOMAIN:
552 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->l_account_domain);
554 case LSA_POLICY_INFO_ROLE:
555 info->role.role = LSA_ROLE_PRIMARY;
558 case LSA_POLICY_INFO_DNS:
559 case LSA_POLICY_INFO_DNS_INT:
560 return dcesrv_lsa_info_DNS(state, mem_ctx, &info->dns);
562 case LSA_POLICY_INFO_REPLICA:
563 ZERO_STRUCT(info->replica);
566 case LSA_POLICY_INFO_QUOTA:
567 ZERO_STRUCT(info->quota);
570 case LSA_POLICY_INFO_MOD:
571 case LSA_POLICY_INFO_AUDIT_FULL_SET:
572 case LSA_POLICY_INFO_AUDIT_FULL_QUERY:
573 /* windows gives INVALID_PARAMETER */
575 return NT_STATUS_INVALID_PARAMETER;
579 return NT_STATUS_INVALID_INFO_CLASS;
585 static NTSTATUS dcesrv_lsa_QueryInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
586 struct lsa_QueryInfoPolicy *r)
588 struct lsa_QueryInfoPolicy2 r2;
593 r2.in.handle = r->in.handle;
594 r2.in.level = r->in.level;
595 r2.out.info = r->out.info;
597 status = dcesrv_lsa_QueryInfoPolicy2(dce_call, mem_ctx, &r2);
605 static NTSTATUS dcesrv_lsa_SetInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
606 struct lsa_SetInfoPolicy *r)
608 /* need to support this */
609 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
616 static NTSTATUS dcesrv_lsa_ClearAuditLog(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
617 struct lsa_ClearAuditLog *r)
619 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
626 This call does not seem to have any long-term effects, hence no database operations
628 we need to talk to the MS product group to find out what this account database means!
630 answer is that the lsa database is totally separate from the SAM and
631 ldap databases. We are going to need a separate ldb to store these
632 accounts. The SIDs on this account bear no relation to the SIDs in
635 static NTSTATUS dcesrv_lsa_CreateAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
636 struct lsa_CreateAccount *r)
638 struct lsa_account_state *astate;
640 struct lsa_policy_state *state;
641 struct dcesrv_handle *h, *ah;
643 ZERO_STRUCTP(r->out.acct_handle);
645 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
649 astate = talloc(dce_call->conn, struct lsa_account_state);
650 if (astate == NULL) {
651 return NT_STATUS_NO_MEMORY;
654 astate->account_sid = dom_sid_dup(astate, r->in.sid);
655 if (astate->account_sid == NULL) {
657 return NT_STATUS_NO_MEMORY;
660 astate->policy = talloc_reference(astate, state);
661 astate->access_mask = r->in.access_mask;
663 ah = dcesrv_handle_new(dce_call->context, LSA_HANDLE_ACCOUNT);
666 return NT_STATUS_NO_MEMORY;
669 ah->data = talloc_steal(ah, astate);
671 *r->out.acct_handle = ah->wire_handle;
680 static NTSTATUS dcesrv_lsa_EnumAccounts(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
681 struct lsa_EnumAccounts *r)
683 struct dcesrv_handle *h;
684 struct lsa_policy_state *state;
686 struct ldb_message **res;
687 const char * const attrs[] = { "objectSid", NULL};
690 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
694 /* NOTE: This call must only return accounts that have at least
697 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
698 "(&(objectSid=*)(privilege=*))");
700 return NT_STATUS_INTERNAL_DB_CORRUPTION;
703 if (*r->in.resume_handle >= ret) {
704 return NT_STATUS_NO_MORE_ENTRIES;
707 count = ret - *r->in.resume_handle;
708 if (count > r->in.num_entries) {
709 count = r->in.num_entries;
713 return NT_STATUS_NO_MORE_ENTRIES;
716 r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, count);
717 if (r->out.sids->sids == NULL) {
718 return NT_STATUS_NO_MEMORY;
721 for (i=0;i<count;i++) {
722 r->out.sids->sids[i].sid =
723 samdb_result_dom_sid(r->out.sids->sids,
724 res[i + *r->in.resume_handle],
726 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
729 r->out.sids->num_sids = count;
730 *r->out.resume_handle = count + *r->in.resume_handle;
736 /* This decrypts and returns Trusted Domain Auth Information Internal data */
737 static NTSTATUS get_trustdom_auth_blob(struct dcesrv_call_state *dce_call,
738 TALLOC_CTX *mem_ctx, DATA_BLOB *auth_blob,
739 struct trustDomainPasswords *auth_struct)
741 DATA_BLOB session_key = data_blob(NULL, 0);
742 enum ndr_err_code ndr_err;
745 nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
746 if (!NT_STATUS_IS_OK(nt_status)) {
750 arcfour_crypt_blob(auth_blob->data, auth_blob->length, &session_key);
751 ndr_err = ndr_pull_struct_blob(auth_blob, mem_ctx,
752 lp_iconv_convenience(dce_call->conn->dce_ctx->lp_ctx),
754 (ndr_pull_flags_fn_t)ndr_pull_trustDomainPasswords);
755 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
756 return NT_STATUS_INVALID_PARAMETER;
762 static NTSTATUS get_trustauth_inout_blob(struct dcesrv_call_state *dce_call,
764 struct trustCurrentPasswords *iopw,
765 DATA_BLOB *trustauth_blob)
768 struct trustAuthInOutBlob ioblob;
769 enum ndr_err_code ndr_err;
771 ioblob.count = iopw->count;
772 ioblob.current = talloc(mem_ctx,
773 struct AuthenticationInformationArray);
774 if (!ioblob.current) {
775 return NT_STATUS_NO_MEMORY;
778 ioblob.current->array = *iopw->current;
779 if (!ioblob.current->array) {
780 return NT_STATUS_NO_MEMORY;
783 ioblob.previous = talloc(mem_ctx,
784 struct AuthenticationInformationArray);
785 if (!ioblob.previous) {
786 return NT_STATUS_NO_MEMORY;
788 ioblob.previous->array = talloc_array(mem_ctx,
789 struct AuthenticationInformation,
791 if (!ioblob.previous->array) {
792 return NT_STATUS_NO_MEMORY;
795 for (i = 0; i < ioblob.count; i++) {
796 ioblob.previous->array[i].LastUpdateTime = 0;
797 ioblob.previous->array[i].AuthType = 0;
799 ndr_err = ndr_push_struct_blob(trustauth_blob, mem_ctx,
800 lp_iconv_convenience(dce_call->conn->dce_ctx->lp_ctx),
802 (ndr_push_flags_fn_t)ndr_push_trustAuthInOutBlob);
803 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
804 return NT_STATUS_INVALID_PARAMETER;
810 static NTSTATUS add_trust_user(TALLOC_CTX *mem_ctx,
811 struct ldb_context *sam_ldb,
812 struct ldb_dn *base_dn,
813 const char *netbios_name,
814 struct trustCurrentPasswords *in,
815 struct ldb_dn **user_dn)
817 struct ldb_message *msg;
822 dn = ldb_dn_copy(mem_ctx, base_dn);
824 return NT_STATUS_NO_MEMORY;
826 if (!ldb_dn_add_child_fmt(dn, "cn=%s$,cn=users", netbios_name)) {
827 return NT_STATUS_NO_MEMORY;
830 msg = ldb_msg_new(mem_ctx);
832 return NT_STATUS_NO_MEMORY;
836 ret = ldb_msg_add_string(msg, "objectClass", "user");
837 if (ret != LDB_SUCCESS) {
838 return NT_STATUS_NO_MEMORY;
841 ret = ldb_msg_add_fmt(msg, "samAccountName", "%s$", netbios_name);
842 if (ret != LDB_SUCCESS) {
843 return NT_STATUS_NO_MEMORY;
846 ret = ldb_msg_add_fmt(msg, "userAccountControl", "%u",
847 UF_INTERDOMAIN_TRUST_ACCOUNT);
848 if (ret != LDB_SUCCESS) {
849 return NT_STATUS_NO_MEMORY;
852 for (i = 0; i < in->count; i++) {
853 const char *attribute;
855 switch (in->current[i]->AuthType) {
856 case TRUST_AUTH_TYPE_NT4OWF:
857 attribute = "unicodePwd";
858 v.data = (uint8_t *)&in->current[i]->AuthInfo.nt4owf.password;
861 case TRUST_AUTH_TYPE_CLEAR:
862 attribute = "clearTextPassword";
863 v.data = in->current[i]->AuthInfo.clear.password;
864 v.length = in->current[i]->AuthInfo.clear.size;
870 ret = ldb_msg_add_value(msg, attribute, &v, NULL);
871 if (ret != LDB_SUCCESS) {
872 return NT_STATUS_NO_MEMORY;
876 /* create the trusted_domain user account */
877 ret = ldb_add(sam_ldb, msg);
878 if (ret != LDB_SUCCESS) {
879 DEBUG(0,("Failed to create user record %s: %s\n",
880 ldb_dn_get_linearized(msg->dn),
881 ldb_errstring(sam_ldb)));
884 case LDB_ERR_ENTRY_ALREADY_EXISTS:
885 return NT_STATUS_DOMAIN_EXISTS;
886 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
887 return NT_STATUS_ACCESS_DENIED;
889 return NT_STATUS_INTERNAL_DB_CORRUPTION;
900 lsa_CreateTrustedDomainEx2
902 static NTSTATUS dcesrv_lsa_CreateTrustedDomain_base(struct dcesrv_call_state *dce_call,
904 struct lsa_CreateTrustedDomainEx2 *r,
907 struct dcesrv_handle *policy_handle;
908 struct lsa_policy_state *policy_state;
909 struct lsa_trusted_domain_state *trusted_domain_state;
910 struct dcesrv_handle *handle;
911 struct ldb_message **msgs, *msg;
912 const char *attrs[] = {
915 const char *netbios_name;
916 const char *dns_name;
918 DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
919 struct trustDomainPasswords auth_struct;
922 struct ldb_context *sam_ldb;
924 DCESRV_PULL_HANDLE(policy_handle, r->in.policy_handle, LSA_HANDLE_POLICY);
925 ZERO_STRUCTP(r->out.trustdom_handle);
927 policy_state = policy_handle->data;
928 sam_ldb = policy_state->sam_ldb;
930 netbios_name = r->in.info->netbios_name.string;
932 return NT_STATUS_INVALID_PARAMETER;
935 dns_name = r->in.info->domain_name.string;
937 trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
938 if (!trusted_domain_state) {
939 return NT_STATUS_NO_MEMORY;
941 trusted_domain_state->policy = policy_state;
943 if (strcasecmp(netbios_name, "BUILTIN") == 0
944 || (dns_name && strcasecmp(dns_name, "BUILTIN") == 0)
945 || (dom_sid_in_domain(policy_state->builtin_sid, r->in.info->sid))) {
946 return NT_STATUS_INVALID_PARAMETER;
949 if (strcasecmp(netbios_name, policy_state->domain_name) == 0
950 || strcasecmp(netbios_name, policy_state->domain_dns) == 0
951 || (dns_name && strcasecmp(dns_name, policy_state->domain_dns) == 0)
952 || (dns_name && strcasecmp(dns_name, policy_state->domain_name) == 0)
953 || (dom_sid_equal(policy_state->domain_sid, r->in.info->sid))) {
954 return NT_STATUS_CURRENT_DOMAIN_NOT_ALLOWED;
957 /* While this is a REF pointer, some of the functions that wrap this don't provide this */
958 if (op == NDR_LSA_CREATETRUSTEDDOMAIN) {
959 /* No secrets are created at this time, for this function */
960 auth_struct.outgoing.count = 0;
961 auth_struct.incoming.count = 0;
963 auth_blob = data_blob_const(r->in.auth_info->auth_blob.data,
964 r->in.auth_info->auth_blob.size);
965 nt_status = get_trustdom_auth_blob(dce_call, mem_ctx,
966 &auth_blob, &auth_struct);
967 if (!NT_STATUS_IS_OK(nt_status)) {
971 if (op == NDR_LSA_CREATETRUSTEDDOMAINEX) {
972 if (auth_struct.incoming.count > 1) {
973 return NT_STATUS_INVALID_PARAMETER;
978 if (auth_struct.incoming.count) {
979 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
980 &auth_struct.incoming,
982 if (!NT_STATUS_IS_OK(nt_status)) {
986 trustAuthIncoming = data_blob(NULL, 0);
989 if (auth_struct.outgoing.count) {
990 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
991 &auth_struct.outgoing,
993 if (!NT_STATUS_IS_OK(nt_status)) {
997 trustAuthOutgoing = data_blob(NULL, 0);
1000 ret = ldb_transaction_start(sam_ldb);
1001 if (ret != LDB_SUCCESS) {
1002 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1006 char *dns_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
1007 char *netbios_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
1008 /* search for the trusted_domain record */
1009 ret = gendb_search(sam_ldb,
1010 mem_ctx, policy_state->system_dn, &msgs, attrs,
1011 "(&(|(flatname=%s)(cn=%s)(trustPartner=%s)(flatname=%s)(cn=%s)(trustPartner=%s))(objectclass=trustedDomain))",
1012 dns_encoded, dns_encoded, dns_encoded, netbios_encoded, netbios_encoded, netbios_encoded);
1014 ldb_transaction_cancel(sam_ldb);
1015 return NT_STATUS_OBJECT_NAME_COLLISION;
1018 char *netbios_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
1019 /* search for the trusted_domain record */
1020 ret = gendb_search(sam_ldb,
1021 mem_ctx, policy_state->system_dn, &msgs, attrs,
1022 "(&(|(flatname=%s)(cn=%s)(trustPartner=%s))(objectclass=trustedDomain))",
1023 netbios_encoded, netbios_encoded, netbios_encoded);
1025 ldb_transaction_cancel(sam_ldb);
1026 return NT_STATUS_OBJECT_NAME_COLLISION;
1031 ldb_transaction_cancel(sam_ldb);
1032 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1035 name = dns_name ? dns_name : netbios_name;
1037 msg = ldb_msg_new(mem_ctx);
1039 return NT_STATUS_NO_MEMORY;
1042 msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
1043 if ( ! ldb_dn_add_child_fmt(msg->dn, "cn=%s", name)) {
1044 ldb_transaction_cancel(sam_ldb);
1045 return NT_STATUS_NO_MEMORY;
1048 samdb_msg_add_string(sam_ldb, mem_ctx, msg, "flatname", netbios_name);
1050 if (r->in.info->sid) {
1051 ret = samdb_msg_add_dom_sid(sam_ldb, mem_ctx, msg, "securityIdentifier", r->in.info->sid);
1052 if (ret != LDB_SUCCESS) {
1053 ldb_transaction_cancel(sam_ldb);
1054 return NT_STATUS_INVALID_PARAMETER;
1058 samdb_msg_add_string(sam_ldb, mem_ctx, msg, "objectClass", "trustedDomain");
1060 samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustType", r->in.info->trust_type);
1062 samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustAttributes", r->in.info->trust_attributes);
1064 samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustDirection", r->in.info->trust_direction);
1067 samdb_msg_add_string(sam_ldb, mem_ctx, msg, "trustPartner", dns_name);
1070 if (trustAuthIncoming.data) {
1071 ret = ldb_msg_add_value(msg, "trustAuthIncoming", &trustAuthIncoming, NULL);
1072 if (ret != LDB_SUCCESS) {
1073 ldb_transaction_cancel(sam_ldb);
1074 return NT_STATUS_NO_MEMORY;
1077 if (trustAuthOutgoing.data) {
1078 ret = ldb_msg_add_value(msg, "trustAuthOutgoing", &trustAuthOutgoing, NULL);
1079 if (ret != LDB_SUCCESS) {
1080 ldb_transaction_cancel(sam_ldb);
1081 return NT_STATUS_NO_MEMORY;
1085 trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msg->dn);
1087 /* create the trusted_domain */
1088 ret = ldb_add(sam_ldb, msg);
1092 case LDB_ERR_ENTRY_ALREADY_EXISTS:
1093 ldb_transaction_cancel(sam_ldb);
1094 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1095 ldb_dn_get_linearized(msg->dn),
1096 ldb_errstring(sam_ldb)));
1097 return NT_STATUS_DOMAIN_EXISTS;
1098 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1099 ldb_transaction_cancel(sam_ldb);
1100 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1101 ldb_dn_get_linearized(msg->dn),
1102 ldb_errstring(sam_ldb)));
1103 return NT_STATUS_ACCESS_DENIED;
1105 ldb_transaction_cancel(sam_ldb);
1106 DEBUG(0,("Failed to create user record %s: %s\n",
1107 ldb_dn_get_linearized(msg->dn),
1108 ldb_errstring(sam_ldb)));
1109 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1112 if (r->in.info->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
1113 struct ldb_dn *user_dn;
1114 /* Inbound trusts must also create a cn=users object to match */
1115 nt_status = add_trust_user(mem_ctx, sam_ldb,
1116 policy_state->domain_dn,
1118 &auth_struct.incoming,
1120 if (!NT_STATUS_IS_OK(nt_status)) {
1121 ldb_transaction_cancel(sam_ldb);
1125 /* save the trust user dn */
1126 trusted_domain_state->trusted_domain_user_dn
1127 = talloc_steal(trusted_domain_state, user_dn);
1130 ret = ldb_transaction_commit(sam_ldb);
1131 if (ret != LDB_SUCCESS) {
1132 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1135 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1137 return NT_STATUS_NO_MEMORY;
1140 handle->data = talloc_steal(handle, trusted_domain_state);
1142 trusted_domain_state->access_mask = r->in.access_mask;
1143 trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
1145 *r->out.trustdom_handle = handle->wire_handle;
1147 return NT_STATUS_OK;
1151 lsa_CreateTrustedDomainEx2
1153 static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx2(struct dcesrv_call_state *dce_call,
1154 TALLOC_CTX *mem_ctx,
1155 struct lsa_CreateTrustedDomainEx2 *r)
1157 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, r, NDR_LSA_CREATETRUSTEDDOMAINEX2);
1160 lsa_CreateTrustedDomainEx
1162 static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx(struct dcesrv_call_state *dce_call,
1163 TALLOC_CTX *mem_ctx,
1164 struct lsa_CreateTrustedDomainEx *r)
1166 struct lsa_CreateTrustedDomainEx2 r2;
1168 r2.in.policy_handle = r->in.policy_handle;
1169 r2.in.info = r->in.info;
1170 r2.in.auth_info = r->in.auth_info;
1171 r2.out.trustdom_handle = r->out.trustdom_handle;
1172 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAINEX);
1176 lsa_CreateTrustedDomain
1178 static NTSTATUS dcesrv_lsa_CreateTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1179 struct lsa_CreateTrustedDomain *r)
1181 struct lsa_CreateTrustedDomainEx2 r2;
1183 r2.in.policy_handle = r->in.policy_handle;
1184 r2.in.info = talloc(mem_ctx, struct lsa_TrustDomainInfoInfoEx);
1186 return NT_STATUS_NO_MEMORY;
1189 r2.in.info->domain_name.string = NULL;
1190 r2.in.info->netbios_name = r->in.info->name;
1191 r2.in.info->sid = r->in.info->sid;
1192 r2.in.info->trust_direction = LSA_TRUST_DIRECTION_OUTBOUND;
1193 r2.in.info->trust_type = LSA_TRUST_TYPE_DOWNLEVEL;
1194 r2.in.info->trust_attributes = 0;
1196 r2.in.access_mask = r->in.access_mask;
1197 r2.out.trustdom_handle = r->out.trustdom_handle;
1199 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAIN);
1204 lsa_OpenTrustedDomain
1206 static NTSTATUS dcesrv_lsa_OpenTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1207 struct lsa_OpenTrustedDomain *r)
1209 struct dcesrv_handle *policy_handle;
1211 struct lsa_policy_state *policy_state;
1212 struct lsa_trusted_domain_state *trusted_domain_state;
1213 struct dcesrv_handle *handle;
1214 struct ldb_message **msgs;
1215 const char *attrs[] = {
1221 const char *sid_string;
1224 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1225 ZERO_STRUCTP(r->out.trustdom_handle);
1226 policy_state = policy_handle->data;
1228 trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
1229 if (!trusted_domain_state) {
1230 return NT_STATUS_NO_MEMORY;
1232 trusted_domain_state->policy = policy_state;
1234 sid_string = dom_sid_string(mem_ctx, r->in.sid);
1236 return NT_STATUS_NO_MEMORY;
1239 /* search for the trusted_domain record */
1240 ret = gendb_search(trusted_domain_state->policy->sam_ldb,
1241 mem_ctx, policy_state->system_dn, &msgs, attrs,
1242 "(&(securityIdentifier=%s)(objectclass=trustedDomain))",
1245 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1249 DEBUG(0,("Found %d records matching DN %s\n", ret,
1250 ldb_dn_get_linearized(policy_state->system_dn)));
1251 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1254 trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msgs[0]->dn);
1256 trusted_domain_state->trusted_domain_user_dn = NULL;
1258 if (ldb_msg_find_attr_as_int(msgs[0], "trustDirection", 0) & LSA_TRUST_DIRECTION_INBOUND) {
1259 const char *flatname = ldb_binary_encode_string(mem_ctx, ldb_msg_find_attr_as_string(msgs[0], "flatname", NULL));
1260 /* search for the trusted_domain record */
1261 ret = gendb_search(trusted_domain_state->policy->sam_ldb,
1262 mem_ctx, policy_state->domain_dn, &msgs, attrs,
1263 "(&(samaccountname=%s$)(objectclass=user)(userAccountControl:1.2.840.113556.1.4.803:=%d))",
1264 flatname, UF_INTERDOMAIN_TRUST_ACCOUNT);
1266 trusted_domain_state->trusted_domain_user_dn = talloc_steal(trusted_domain_state, msgs[0]->dn);
1269 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1271 return NT_STATUS_NO_MEMORY;
1274 handle->data = talloc_steal(handle, trusted_domain_state);
1276 trusted_domain_state->access_mask = r->in.access_mask;
1277 trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
1279 *r->out.trustdom_handle = handle->wire_handle;
1281 return NT_STATUS_OK;
1286 lsa_OpenTrustedDomainByName
1288 static NTSTATUS dcesrv_lsa_OpenTrustedDomainByName(struct dcesrv_call_state *dce_call,
1289 TALLOC_CTX *mem_ctx,
1290 struct lsa_OpenTrustedDomainByName *r)
1292 struct dcesrv_handle *policy_handle;
1294 struct lsa_policy_state *policy_state;
1295 struct lsa_trusted_domain_state *trusted_domain_state;
1296 struct dcesrv_handle *handle;
1297 struct ldb_message **msgs;
1298 const char *attrs[] = {
1304 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1305 ZERO_STRUCTP(r->out.trustdom_handle);
1306 policy_state = policy_handle->data;
1308 if (!r->in.name.string) {
1309 return NT_STATUS_INVALID_PARAMETER;
1312 trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
1313 if (!trusted_domain_state) {
1314 return NT_STATUS_NO_MEMORY;
1316 trusted_domain_state->policy = policy_state;
1318 /* search for the trusted_domain record */
1319 td_name = ldb_binary_encode_string(mem_ctx, r->in.name.string);
1320 ret = gendb_search(trusted_domain_state->policy->sam_ldb,
1321 mem_ctx, policy_state->system_dn, &msgs, attrs,
1322 "(&(|(flatname=%s)(cn=%s)(trustPartner=%s))"
1323 "(objectclass=trustedDomain))",
1324 td_name, td_name, td_name);
1326 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1330 DEBUG(0,("Found %d records matching DN %s\n", ret,
1331 ldb_dn_get_linearized(policy_state->system_dn)));
1332 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1335 /* TODO: perform access checks */
1337 trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msgs[0]->dn);
1339 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1341 return NT_STATUS_NO_MEMORY;
1344 handle->data = talloc_steal(handle, trusted_domain_state);
1346 trusted_domain_state->access_mask = r->in.access_mask;
1347 trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
1349 *r->out.trustdom_handle = handle->wire_handle;
1351 return NT_STATUS_OK;
1357 lsa_SetTrustedDomainInfo
1359 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1360 struct lsa_SetTrustedDomainInfo *r)
1362 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1367 /* parameters 4 to 6 are optional if the dn is a dn of a TDO object,
1368 * otherwise at least one must be provided */
1369 static NTSTATUS get_tdo(struct ldb_context *sam, TALLOC_CTX *mem_ctx,
1370 struct ldb_dn *basedn, const char *dns_domain,
1371 const char *netbios, struct dom_sid2 *sid,
1372 struct ldb_message ***msgs)
1374 const char *attrs[] = { "flatname", "trustPartner",
1375 "securityIdentifier", "trustDirection",
1376 "trustType", "trustAttributes",
1378 "msDs-supportedEncryptionTypes", NULL };
1381 char *sidstr = NULL;
1386 if (dns_domain || netbios || sid) {
1387 filter = talloc_strdup(mem_ctx,
1388 "(&(objectclass=trustedDomain)(|");
1390 filter = talloc_strdup(mem_ctx,
1391 "(objectclass=trustedDomain)");
1394 return NT_STATUS_NO_MEMORY;
1398 dns = ldb_binary_encode_string(mem_ctx, dns_domain);
1400 return NT_STATUS_NO_MEMORY;
1402 filter = talloc_asprintf_append(filter,
1403 "(trustPartner=%s)", dns);
1405 return NT_STATUS_NO_MEMORY;
1409 nbn = ldb_binary_encode_string(mem_ctx, netbios);
1411 return NT_STATUS_NO_MEMORY;
1413 filter = talloc_asprintf_append(filter,
1414 "(flatname=%s)", nbn);
1416 return NT_STATUS_NO_MEMORY;
1420 sidstr = dom_sid_string(mem_ctx, sid);
1422 return NT_STATUS_INVALID_PARAMETER;
1424 filter = talloc_asprintf_append(filter,
1425 "(securityIdentifier=%s)",
1428 return NT_STATUS_NO_MEMORY;
1431 if (dns_domain || netbios || sid) {
1432 filter = talloc_asprintf_append(filter, "))");
1434 return NT_STATUS_NO_MEMORY;
1438 ret = gendb_search(sam, mem_ctx, basedn, msgs, attrs, "%s", filter);
1440 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1444 return NT_STATUS_OBJECT_NAME_COLLISION;
1447 return NT_STATUS_OK;
1450 static NTSTATUS update_uint32_t_value(TALLOC_CTX *mem_ctx,
1451 struct ldb_message *orig,
1452 struct ldb_message *dest,
1453 const char *attribute,
1455 uint32_t *orig_value)
1457 const struct ldb_val *orig_val;
1458 uint32_t orig_uint = 0;
1463 orig_val = ldb_msg_find_ldb_val(orig, attribute);
1464 if (!orig_val || !orig_val->data) {
1465 /* add new attribute */
1466 flags = LDB_FLAG_MOD_ADD;
1470 orig_uint = strtoul((const char *)orig_val->data, NULL, 0);
1471 if (errno != 0 || orig_uint != value) {
1472 /* replace also if can't get value */
1473 flags = LDB_FLAG_MOD_REPLACE;
1478 /* stored value is identical, nothing to change */
1482 ret = ldb_msg_add_empty(dest, attribute, flags, NULL);
1483 if (ret != LDB_SUCCESS) {
1484 return NT_STATUS_NO_MEMORY;
1487 str_val = talloc_asprintf(mem_ctx, "%u", value);
1489 return NT_STATUS_NO_MEMORY;
1491 ret = ldb_msg_add_steal_string(dest, attribute, str_val);
1492 if (ret != LDB_SUCCESS) {
1493 return NT_STATUS_NO_MEMORY;
1498 *orig_value = orig_uint;
1500 return NT_STATUS_OK;
1503 static NTSTATUS update_trust_user(TALLOC_CTX *mem_ctx,
1504 struct ldb_context *sam_ldb,
1505 struct ldb_dn *base_dn,
1507 const char *netbios_name,
1508 struct trustCurrentPasswords *in)
1510 const char *attrs[] = { "userAccountControl", NULL };
1511 struct ldb_message **msgs;
1512 struct ldb_message *msg;
1517 ret = gendb_search(sam_ldb, mem_ctx,
1518 base_dn, &msgs, attrs,
1519 "samAccountName=%s$", netbios_name);
1521 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1526 return NT_STATUS_OK;
1529 /* ok no existing user, add it from scratch */
1530 return add_trust_user(mem_ctx, sam_ldb, base_dn,
1531 netbios_name, in, NULL);
1534 /* check user is what we are looking for */
1535 uac = ldb_msg_find_attr_as_uint(msgs[0],
1536 "userAccountControl", 0);
1537 if (!(uac & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
1538 return NT_STATUS_OBJECT_NAME_COLLISION;
1542 ret = ldb_delete(sam_ldb, msgs[0]->dn);
1545 return NT_STATUS_OK;
1546 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1547 return NT_STATUS_ACCESS_DENIED;
1549 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1553 /* entry exists, just modify secret if any */
1554 if (in->count == 0) {
1555 return NT_STATUS_OK;
1558 msg = ldb_msg_new(mem_ctx);
1560 return NT_STATUS_NO_MEMORY;
1562 msg->dn = msgs[0]->dn;
1564 for (i = 0; i < in->count; i++) {
1565 const char *attribute;
1567 switch (in->current[i]->AuthType) {
1568 case TRUST_AUTH_TYPE_NT4OWF:
1569 attribute = "unicodePwd";
1570 v.data = (uint8_t *)&in->current[i]->AuthInfo.nt4owf.password;
1573 case TRUST_AUTH_TYPE_CLEAR:
1574 attribute = "clearTextPassword";
1575 v.data = in->current[i]->AuthInfo.clear.password;
1576 v.length = in->current[i]->AuthInfo.clear.size;
1582 ret = ldb_msg_add_empty(msg, attribute,
1583 LDB_FLAG_MOD_REPLACE, NULL);
1584 if (ret != LDB_SUCCESS) {
1585 return NT_STATUS_NO_MEMORY;
1588 ret = ldb_msg_add_value(msg, attribute, &v, NULL);
1589 if (ret != LDB_SUCCESS) {
1590 return NT_STATUS_NO_MEMORY;
1594 /* create the trusted_domain user account */
1595 ret = ldb_modify(sam_ldb, msg);
1596 if (ret != LDB_SUCCESS) {
1597 DEBUG(0,("Failed to create user record %s: %s\n",
1598 ldb_dn_get_linearized(msg->dn),
1599 ldb_errstring(sam_ldb)));
1602 case LDB_ERR_ENTRY_ALREADY_EXISTS:
1603 return NT_STATUS_DOMAIN_EXISTS;
1604 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1605 return NT_STATUS_ACCESS_DENIED;
1607 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1611 return NT_STATUS_OK;
1615 static NTSTATUS setInfoTrustedDomain_base(struct dcesrv_call_state *dce_call,
1616 struct dcesrv_handle *p_handle,
1617 TALLOC_CTX *mem_ctx,
1618 struct ldb_message *dom_msg,
1619 enum lsa_TrustDomInfoEnum level,
1620 union lsa_TrustedDomainInfo *info)
1622 struct lsa_policy_state *p_state = p_handle->data;
1623 uint32_t *posix_offset = NULL;
1624 struct lsa_TrustDomainInfoInfoEx *info_ex = NULL;
1625 struct lsa_TrustDomainInfoAuthInfo *auth_info = NULL;
1626 struct lsa_TrustDomainInfoAuthInfoInternal *auth_info_int = NULL;
1627 uint32_t *enc_types = NULL;
1628 DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
1629 struct trustDomainPasswords auth_struct;
1631 struct ldb_message **msgs;
1632 struct ldb_message *msg;
1633 bool add_outgoing = false;
1634 bool add_incoming = false;
1635 bool del_outgoing = false;
1636 bool del_incoming = false;
1637 bool in_transaction = false;
1642 case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
1643 posix_offset = &info->posix_offset.posix_offset;
1645 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
1646 info_ex = &info->info_ex;
1648 case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO:
1649 auth_info = &info->auth_info;
1651 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
1652 posix_offset = &info->full_info.posix_offset.posix_offset;
1653 info_ex = &info->full_info.info_ex;
1654 auth_info = &info->full_info.auth_info;
1656 case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO_INTERNAL:
1657 auth_info_int = &info->auth_info_internal;
1659 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_INTERNAL:
1660 posix_offset = &info->full_info_internal.posix_offset.posix_offset;
1661 info_ex = &info->full_info_internal.info_ex;
1662 auth_info_int = &info->full_info_internal.auth_info;
1664 case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
1665 enc_types = &info->enc_types.enc_types;
1668 return NT_STATUS_INVALID_PARAMETER;
1672 /* FIXME: not handled yet */
1673 return NT_STATUS_INVALID_PARAMETER;
1676 /* decode auth_info_int if set */
1677 if (auth_info_int) {
1679 /* now decrypt blob */
1680 auth_blob = data_blob_const(auth_info_int->auth_blob.data,
1681 auth_info_int->auth_blob.size);
1683 nt_status = get_trustdom_auth_blob(dce_call, mem_ctx,
1684 &auth_blob, &auth_struct);
1685 if (!NT_STATUS_IS_OK(nt_status)) {
1691 /* verify data matches */
1692 if (info_ex->trust_attributes &
1693 LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
1694 /* TODO: check what behavior level we have */
1695 if (strcasecmp_m(p_state->domain_dns,
1696 p_state->forest_dns) != 0) {
1697 return NT_STATUS_INVALID_DOMAIN_STATE;
1701 ret = samdb_rodc(p_state->sam_ldb, &am_rodc);
1702 if (ret == LDB_SUCCESS && am_rodc) {
1703 return NT_STATUS_NO_SUCH_DOMAIN;
1706 /* verify only one object matches the dns/netbios/sid
1707 * triplet and that this is the one we already have */
1708 nt_status = get_tdo(p_state->sam_ldb, mem_ctx,
1710 info_ex->domain_name.string,
1711 info_ex->netbios_name.string,
1712 info_ex->sid, &msgs);
1713 if (!NT_STATUS_IS_OK(nt_status)) {
1716 if (ldb_dn_compare(dom_msg->dn, msgs[0]->dn) != 0) {
1717 return NT_STATUS_OBJECT_NAME_COLLISION;
1722 /* TODO: should we fetch previous values from the existing entry
1723 * and append them ? */
1724 if (auth_struct.incoming.count) {
1725 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1726 &auth_struct.incoming,
1727 &trustAuthIncoming);
1728 if (!NT_STATUS_IS_OK(nt_status)) {
1732 trustAuthIncoming = data_blob(NULL, 0);
1735 if (auth_struct.outgoing.count) {
1736 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1737 &auth_struct.outgoing,
1738 &trustAuthOutgoing);
1739 if (!NT_STATUS_IS_OK(nt_status)) {
1743 trustAuthOutgoing = data_blob(NULL, 0);
1746 msg = ldb_msg_new(mem_ctx);
1748 return NT_STATUS_NO_MEMORY;
1750 msg->dn = dom_msg->dn;
1753 nt_status = update_uint32_t_value(mem_ctx, dom_msg, msg,
1755 *posix_offset, NULL);
1756 if (!NT_STATUS_IS_OK(nt_status)) {
1767 nt_status = update_uint32_t_value(mem_ctx, dom_msg, msg,
1769 info_ex->trust_direction,
1771 if (!NT_STATUS_IS_OK(nt_status)) {
1775 tmp = info_ex->trust_direction ^ origdir;
1776 if (tmp & LSA_TRUST_DIRECTION_INBOUND) {
1777 if (origdir & LSA_TRUST_DIRECTION_INBOUND) {
1778 del_incoming = true;
1780 add_incoming = true;
1783 if (tmp & LSA_TRUST_DIRECTION_OUTBOUND) {
1784 if (origdir & LSA_TRUST_DIRECTION_OUTBOUND) {
1785 del_outgoing = true;
1787 add_outgoing = true;
1791 origtype = ldb_msg_find_attr_as_int(dom_msg, "trustType", -1);
1792 if (origtype == -1 || origtype != info_ex->trust_type) {
1793 DEBUG(1, ("Attempted to change trust type! "
1794 "Operation not handled\n"));
1795 return NT_STATUS_INVALID_PARAMETER;
1798 nt_status = update_uint32_t_value(mem_ctx, dom_msg, msg,
1800 info_ex->trust_attributes,
1802 if (!NT_STATUS_IS_OK(nt_status)) {
1805 /* TODO: check forestFunctionality from ldb opaque */
1806 /* TODO: check what is set makes sense */
1807 /* for now refuse changes */
1808 if (origattrs == -1 ||
1809 origattrs != info_ex->trust_attributes) {
1810 DEBUG(1, ("Attempted to change trust attributes! "
1811 "Operation not handled\n"));
1812 return NT_STATUS_INVALID_PARAMETER;
1817 nt_status = update_uint32_t_value(mem_ctx, dom_msg, msg,
1818 "msDS-SupportedEncryptionTypes",
1820 if (!NT_STATUS_IS_OK(nt_status)) {
1825 if (add_incoming && trustAuthIncoming.data) {
1826 ret = ldb_msg_add_empty(msg, "trustAuthIncoming",
1827 LDB_FLAG_MOD_REPLACE, NULL);
1828 if (ret != LDB_SUCCESS) {
1829 return NT_STATUS_NO_MEMORY;
1831 ret = ldb_msg_add_value(msg, "trustAuthIncoming",
1832 &trustAuthIncoming, NULL);
1833 if (ret != LDB_SUCCESS) {
1834 return NT_STATUS_NO_MEMORY;
1837 if (add_outgoing && trustAuthOutgoing.data) {
1838 ret = ldb_msg_add_empty(msg, "trustAuthIncoming",
1839 LDB_FLAG_MOD_REPLACE, NULL);
1840 if (ret != LDB_SUCCESS) {
1841 return NT_STATUS_NO_MEMORY;
1843 ret = ldb_msg_add_value(msg, "trustAuthOutgoing",
1844 &trustAuthOutgoing, NULL);
1845 if (ret != LDB_SUCCESS) {
1846 return NT_STATUS_NO_MEMORY;
1850 /* start transaction */
1851 ret = ldb_transaction_start(p_state->sam_ldb);
1852 if (ret != LDB_SUCCESS) {
1853 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1855 in_transaction = true;
1857 ret = ldb_modify(p_state->sam_ldb, msg);
1858 if (ret != LDB_SUCCESS) {
1859 DEBUG(1,("Failed to modify trusted domain record %s: %s\n",
1860 ldb_dn_get_linearized(msg->dn),
1861 ldb_errstring(p_state->sam_ldb)));
1862 if (ret == LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS) {
1863 nt_status = NT_STATUS_ACCESS_DENIED;
1865 nt_status = NT_STATUS_INTERNAL_DB_CORRUPTION;
1870 if (add_incoming || del_incoming) {
1871 const char *netbios_name;
1873 netbios_name = ldb_msg_find_attr_as_string(dom_msg,
1875 if (!netbios_name) {
1876 nt_status = NT_STATUS_INVALID_DOMAIN_STATE;
1880 nt_status = update_trust_user(mem_ctx,
1885 &auth_struct.incoming);
1886 if (!NT_STATUS_IS_OK(nt_status)) {
1891 /* ok, all fine, commit transaction and return */
1892 ret = ldb_transaction_commit(p_state->sam_ldb);
1893 if (ret != LDB_SUCCESS) {
1894 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1896 in_transaction = false;
1898 nt_status = NT_STATUS_OK;
1901 if (in_transaction) {
1902 ldb_transaction_cancel(p_state->sam_ldb);
1908 lsa_SetInfomrationTrustedDomain
1910 static NTSTATUS dcesrv_lsa_SetInformationTrustedDomain(
1911 struct dcesrv_call_state *dce_call,
1912 TALLOC_CTX *mem_ctx,
1913 struct lsa_SetInformationTrustedDomain *r)
1915 struct dcesrv_handle *h;
1916 struct lsa_trusted_domain_state *td_state;
1917 struct ldb_message **msgs;
1920 DCESRV_PULL_HANDLE(h, r->in.trustdom_handle,
1921 LSA_HANDLE_TRUSTED_DOMAIN);
1923 td_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
1925 /* get the trusted domain object */
1926 nt_status = get_tdo(td_state->policy->sam_ldb, mem_ctx,
1927 td_state->trusted_domain_dn,
1928 NULL, NULL, NULL, &msgs);
1929 if (!NT_STATUS_IS_OK(nt_status)) {
1930 if (NT_STATUS_EQUAL(nt_status,
1931 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1934 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1937 return setInfoTrustedDomain_base(dce_call, h, mem_ctx,
1938 msgs[0], r->in.level, r->in.info);
1943 lsa_DeleteTrustedDomain
1945 static NTSTATUS dcesrv_lsa_DeleteTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1946 struct lsa_DeleteTrustedDomain *r)
1949 struct lsa_OpenTrustedDomain opn;
1950 struct lsa_DeleteObject del;
1951 struct dcesrv_handle *h;
1953 opn.in.handle = r->in.handle;
1954 opn.in.sid = r->in.dom_sid;
1955 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1956 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
1957 if (!opn.out.trustdom_handle) {
1958 return NT_STATUS_NO_MEMORY;
1960 status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
1961 if (!NT_STATUS_IS_OK(status)) {
1965 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
1966 talloc_steal(mem_ctx, h);
1968 del.in.handle = opn.out.trustdom_handle;
1969 del.out.handle = opn.out.trustdom_handle;
1970 status = dcesrv_lsa_DeleteObject(dce_call, mem_ctx, &del);
1971 if (!NT_STATUS_IS_OK(status)) {
1974 return NT_STATUS_OK;
1977 static NTSTATUS fill_trust_domain_ex(TALLOC_CTX *mem_ctx,
1978 struct ldb_message *msg,
1979 struct lsa_TrustDomainInfoInfoEx *info_ex)
1981 info_ex->domain_name.string
1982 = ldb_msg_find_attr_as_string(msg, "trustPartner", NULL);
1983 info_ex->netbios_name.string
1984 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
1986 = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
1987 info_ex->trust_direction
1988 = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
1990 = ldb_msg_find_attr_as_int(msg, "trustType", 0);
1991 info_ex->trust_attributes
1992 = ldb_msg_find_attr_as_int(msg, "trustAttributes", 0);
1993 return NT_STATUS_OK;
1997 lsa_QueryTrustedDomainInfo
1999 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2000 struct lsa_QueryTrustedDomainInfo *r)
2002 union lsa_TrustedDomainInfo *info = NULL;
2003 struct dcesrv_handle *h;
2004 struct lsa_trusted_domain_state *trusted_domain_state;
2005 struct ldb_message *msg;
2007 struct ldb_message **res;
2008 const char *attrs[] = {
2011 "securityIdentifier",
2015 "msDs-supportedEncryptionTypes",
2019 DCESRV_PULL_HANDLE(h, r->in.trustdom_handle, LSA_HANDLE_TRUSTED_DOMAIN);
2021 trusted_domain_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
2023 /* pull all the user attributes */
2024 ret = gendb_search_dn(trusted_domain_state->policy->sam_ldb, mem_ctx,
2025 trusted_domain_state->trusted_domain_dn, &res, attrs);
2027 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2031 info = talloc_zero(mem_ctx, union lsa_TrustedDomainInfo);
2033 return NT_STATUS_NO_MEMORY;
2035 *r->out.info = info;
2037 switch (r->in.level) {
2038 case LSA_TRUSTED_DOMAIN_INFO_NAME:
2039 info->name.netbios_name.string
2040 = samdb_result_string(msg, "flatname", NULL);
2042 case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
2043 info->posix_offset.posix_offset
2044 = samdb_result_uint(msg, "posixOffset", 0);
2046 #if 0 /* Win2k3 doesn't implement this */
2047 case LSA_TRUSTED_DOMAIN_INFO_BASIC:
2048 r->out.info->info_basic.netbios_name.string
2049 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2050 r->out.info->info_basic.sid
2051 = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
2054 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
2055 return fill_trust_domain_ex(mem_ctx, msg, &info->info_ex);
2057 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
2058 ZERO_STRUCT(info->full_info);
2059 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info.info_ex);
2061 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_2_INTERNAL:
2062 ZERO_STRUCT(info->full_info2_internal);
2063 info->full_info2_internal.posix_offset.posix_offset
2064 = samdb_result_uint(msg, "posixOffset", 0);
2065 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info2_internal.info.info_ex);
2067 case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
2068 info->enc_types.enc_types
2069 = samdb_result_uint(msg, "msDs-supportedEncryptionTypes", KERB_ENCTYPE_RC4_HMAC_MD5);
2072 case LSA_TRUSTED_DOMAIN_INFO_CONTROLLERS:
2073 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX2_INTERNAL:
2074 /* oops, we don't want to return the info after all */
2076 *r->out.info = NULL;
2077 return NT_STATUS_INVALID_PARAMETER;
2079 /* oops, we don't want to return the info after all */
2081 *r->out.info = NULL;
2082 return NT_STATUS_INVALID_INFO_CLASS;
2085 return NT_STATUS_OK;
2090 lsa_QueryTrustedDomainInfoBySid
2092 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoBySid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2093 struct lsa_QueryTrustedDomainInfoBySid *r)
2096 struct lsa_OpenTrustedDomain opn;
2097 struct lsa_QueryTrustedDomainInfo query;
2098 struct dcesrv_handle *h;
2100 opn.in.handle = r->in.handle;
2101 opn.in.sid = r->in.dom_sid;
2102 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2103 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2104 if (!opn.out.trustdom_handle) {
2105 return NT_STATUS_NO_MEMORY;
2107 status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
2108 if (!NT_STATUS_IS_OK(status)) {
2112 /* Ensure this handle goes away at the end of this call */
2113 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2114 talloc_steal(mem_ctx, h);
2116 query.in.trustdom_handle = opn.out.trustdom_handle;
2117 query.in.level = r->in.level;
2118 query.out.info = r->out.info;
2119 status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2120 if (!NT_STATUS_IS_OK(status)) {
2124 return NT_STATUS_OK;
2128 lsa_SetTrustedDomainInfoByName
2130 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2131 TALLOC_CTX *mem_ctx,
2132 struct lsa_SetTrustedDomainInfoByName *r)
2134 struct dcesrv_handle *policy_handle;
2135 struct lsa_policy_state *policy_state;
2136 struct ldb_message **msgs;
2139 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2140 policy_state = policy_handle->data;
2142 /* get the trusted domain object */
2143 nt_status = get_tdo(policy_state->sam_ldb, mem_ctx,
2144 policy_state->domain_dn,
2145 r->in.trusted_domain->string,
2146 r->in.trusted_domain->string,
2148 if (!NT_STATUS_IS_OK(nt_status)) {
2149 if (NT_STATUS_EQUAL(nt_status,
2150 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2153 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2156 return setInfoTrustedDomain_base(dce_call, policy_handle, mem_ctx,
2157 msgs[0], r->in.level, r->in.info);
2161 lsa_QueryTrustedDomainInfoByName
2163 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2164 TALLOC_CTX *mem_ctx,
2165 struct lsa_QueryTrustedDomainInfoByName *r)
2168 struct lsa_OpenTrustedDomainByName opn;
2169 struct lsa_QueryTrustedDomainInfo query;
2170 struct dcesrv_handle *h;
2172 opn.in.handle = r->in.handle;
2173 opn.in.name = *r->in.trusted_domain;
2174 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2175 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2176 if (!opn.out.trustdom_handle) {
2177 return NT_STATUS_NO_MEMORY;
2179 status = dcesrv_lsa_OpenTrustedDomainByName(dce_call, mem_ctx, &opn);
2180 if (!NT_STATUS_IS_OK(status)) {
2184 /* Ensure this handle goes away at the end of this call */
2185 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2186 talloc_steal(mem_ctx, h);
2188 query.in.trustdom_handle = opn.out.trustdom_handle;
2189 query.in.level = r->in.level;
2190 query.out.info = r->out.info;
2191 status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2192 if (!NT_STATUS_IS_OK(status)) {
2196 return NT_STATUS_OK;
2200 lsa_CloseTrustedDomainEx
2202 static NTSTATUS dcesrv_lsa_CloseTrustedDomainEx(struct dcesrv_call_state *dce_call,
2203 TALLOC_CTX *mem_ctx,
2204 struct lsa_CloseTrustedDomainEx *r)
2206 /* The result of a bad hair day from an IDL programmer? Not
2207 * implmented in Win2k3. You should always just lsa_Close
2209 return NT_STATUS_NOT_IMPLEMENTED;
2214 comparison function for sorting lsa_DomainInformation array
2216 static int compare_DomainInfo(struct lsa_DomainInfo *e1, struct lsa_DomainInfo *e2)
2218 return strcasecmp_m(e1->name.string, e2->name.string);
2224 static NTSTATUS dcesrv_lsa_EnumTrustDom(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2225 struct lsa_EnumTrustDom *r)
2227 struct dcesrv_handle *policy_handle;
2228 struct lsa_DomainInfo *entries;
2229 struct lsa_policy_state *policy_state;
2230 struct ldb_message **domains;
2231 const char *attrs[] = {
2233 "securityIdentifier",
2240 *r->out.resume_handle = 0;
2242 r->out.domains->domains = NULL;
2243 r->out.domains->count = 0;
2245 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2247 policy_state = policy_handle->data;
2249 /* search for all users in this domain. This could possibly be cached and
2250 resumed based on resume_key */
2251 count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
2252 "objectclass=trustedDomain");
2254 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2257 /* convert to lsa_TrustInformation format */
2258 entries = talloc_array(mem_ctx, struct lsa_DomainInfo, count);
2260 return NT_STATUS_NO_MEMORY;
2262 for (i=0;i<count;i++) {
2263 entries[i].sid = samdb_result_dom_sid(mem_ctx, domains[i], "securityIdentifier");
2264 entries[i].name.string = samdb_result_string(domains[i], "flatname", NULL);
2267 /* sort the results by name */
2268 TYPESAFE_QSORT(entries, count, compare_DomainInfo);
2270 if (*r->in.resume_handle >= count) {
2271 *r->out.resume_handle = -1;
2273 return NT_STATUS_NO_MORE_ENTRIES;
2276 /* return the rest, limit by max_size. Note that we
2277 use the w2k3 element size value of 60 */
2278 r->out.domains->count = count - *r->in.resume_handle;
2279 r->out.domains->count = MIN(r->out.domains->count,
2280 1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_MULTIPLIER));
2282 r->out.domains->domains = entries + *r->in.resume_handle;
2283 r->out.domains->count = r->out.domains->count;
2285 if (r->out.domains->count < count - *r->in.resume_handle) {
2286 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2287 return STATUS_MORE_ENTRIES;
2290 /* according to MS-LSAD 3.1.4.7.8 output resume handle MUST
2291 * always be larger than the previous input resume handle, in
2292 * particular when hitting the last query it is vital to set the
2293 * resume handle correctly to avoid infinite client loops, as
2294 * seen e.g. with Windows XP SP3 when resume handle is 0 and
2295 * status is NT_STATUS_OK - gd */
2297 *r->out.resume_handle = (uint32_t)-1;
2299 return NT_STATUS_OK;
2303 comparison function for sorting lsa_DomainInformation array
2305 static int compare_TrustDomainInfoInfoEx(struct lsa_TrustDomainInfoInfoEx *e1, struct lsa_TrustDomainInfoInfoEx *e2)
2307 return strcasecmp_m(e1->netbios_name.string, e2->netbios_name.string);
2311 lsa_EnumTrustedDomainsEx
2313 static NTSTATUS dcesrv_lsa_EnumTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2314 struct lsa_EnumTrustedDomainsEx *r)
2316 struct dcesrv_handle *policy_handle;
2317 struct lsa_TrustDomainInfoInfoEx *entries;
2318 struct lsa_policy_state *policy_state;
2319 struct ldb_message **domains;
2320 const char *attrs[] = {
2323 "securityIdentifier",
2333 *r->out.resume_handle = 0;
2335 r->out.domains->domains = NULL;
2336 r->out.domains->count = 0;
2338 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2340 policy_state = policy_handle->data;
2342 /* search for all users in this domain. This could possibly be cached and
2343 resumed based on resume_key */
2344 count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
2345 "objectclass=trustedDomain");
2347 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2350 /* convert to lsa_DomainInformation format */
2351 entries = talloc_array(mem_ctx, struct lsa_TrustDomainInfoInfoEx, count);
2353 return NT_STATUS_NO_MEMORY;
2355 for (i=0;i<count;i++) {
2356 nt_status = fill_trust_domain_ex(mem_ctx, domains[i], &entries[i]);
2357 if (!NT_STATUS_IS_OK(nt_status)) {
2362 /* sort the results by name */
2363 TYPESAFE_QSORT(entries, count, compare_TrustDomainInfoInfoEx);
2365 if (*r->in.resume_handle >= count) {
2366 *r->out.resume_handle = -1;
2368 return NT_STATUS_NO_MORE_ENTRIES;
2371 /* return the rest, limit by max_size. Note that we
2372 use the w2k3 element size value of 60 */
2373 r->out.domains->count = count - *r->in.resume_handle;
2374 r->out.domains->count = MIN(r->out.domains->count,
2375 1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_EX_MULTIPLIER));
2377 r->out.domains->domains = entries + *r->in.resume_handle;
2378 r->out.domains->count = r->out.domains->count;
2380 if (r->out.domains->count < count - *r->in.resume_handle) {
2381 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2382 return STATUS_MORE_ENTRIES;
2385 return NT_STATUS_OK;
2392 static NTSTATUS dcesrv_lsa_OpenAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2393 struct lsa_OpenAccount *r)
2395 struct dcesrv_handle *h, *ah;
2396 struct lsa_policy_state *state;
2397 struct lsa_account_state *astate;
2399 ZERO_STRUCTP(r->out.acct_handle);
2401 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2405 astate = talloc(dce_call->conn, struct lsa_account_state);
2406 if (astate == NULL) {
2407 return NT_STATUS_NO_MEMORY;
2410 astate->account_sid = dom_sid_dup(astate, r->in.sid);
2411 if (astate->account_sid == NULL) {
2412 talloc_free(astate);
2413 return NT_STATUS_NO_MEMORY;
2416 astate->policy = talloc_reference(astate, state);
2417 astate->access_mask = r->in.access_mask;
2419 ah = dcesrv_handle_new(dce_call->context, LSA_HANDLE_ACCOUNT);
2421 talloc_free(astate);
2422 return NT_STATUS_NO_MEMORY;
2425 ah->data = talloc_steal(ah, astate);
2427 *r->out.acct_handle = ah->wire_handle;
2429 return NT_STATUS_OK;
2434 lsa_EnumPrivsAccount
2436 static NTSTATUS dcesrv_lsa_EnumPrivsAccount(struct dcesrv_call_state *dce_call,
2437 TALLOC_CTX *mem_ctx,
2438 struct lsa_EnumPrivsAccount *r)
2440 struct dcesrv_handle *h;
2441 struct lsa_account_state *astate;
2444 struct ldb_message **res;
2445 const char * const attrs[] = { "privilege", NULL};
2446 struct ldb_message_element *el;
2448 struct lsa_PrivilegeSet *privs;
2450 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2454 privs = talloc(mem_ctx, struct lsa_PrivilegeSet);
2455 if (privs == NULL) {
2456 return NT_STATUS_NO_MEMORY;
2462 *r->out.privs = privs;
2464 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
2465 if (sidstr == NULL) {
2466 return NT_STATUS_NO_MEMORY;
2469 ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs,
2470 "objectSid=%s", sidstr);
2472 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2475 return NT_STATUS_OK;
2478 el = ldb_msg_find_element(res[0], "privilege");
2479 if (el == NULL || el->num_values == 0) {
2480 return NT_STATUS_OK;
2483 privs->set = talloc_array(privs,
2484 struct lsa_LUIDAttribute, el->num_values);
2485 if (privs->set == NULL) {
2486 return NT_STATUS_NO_MEMORY;
2489 for (i=0;i<el->num_values;i++) {
2490 int id = sec_privilege_id((const char *)el->values[i].data);
2492 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2494 privs->set[i].attribute = 0;
2495 privs->set[i].luid.low = id;
2496 privs->set[i].luid.high = 0;
2499 privs->count = el->num_values;
2501 return NT_STATUS_OK;
2505 lsa_EnumAccountRights
2507 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call,
2508 TALLOC_CTX *mem_ctx,
2509 struct lsa_EnumAccountRights *r)
2511 struct dcesrv_handle *h;
2512 struct lsa_policy_state *state;
2515 struct ldb_message **res;
2516 const char * const attrs[] = { "privilege", NULL};
2518 struct ldb_message_element *el;
2520 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2524 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, r->in.sid);
2525 if (sidstr == NULL) {
2526 return NT_STATUS_NO_MEMORY;
2529 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
2530 "(&(objectSid=%s)(privilege=*))", sidstr);
2532 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2535 DEBUG(3, ("searching for account rights for SID: %s failed: %s",
2536 dom_sid_string(mem_ctx, r->in.sid),
2537 ldb_errstring(state->pdb)));
2538 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2541 el = ldb_msg_find_element(res[0], "privilege");
2542 if (el == NULL || el->num_values == 0) {
2543 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2546 r->out.rights->count = el->num_values;
2547 r->out.rights->names = talloc_array(r->out.rights,
2548 struct lsa_StringLarge, r->out.rights->count);
2549 if (r->out.rights->names == NULL) {
2550 return NT_STATUS_NO_MEMORY;
2553 for (i=0;i<el->num_values;i++) {
2554 r->out.rights->names[i].string = (const char *)el->values[i].data;
2557 return NT_STATUS_OK;
2563 helper for lsa_AddAccountRights and lsa_RemoveAccountRights
2565 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
2566 TALLOC_CTX *mem_ctx,
2567 struct lsa_policy_state *state,
2569 struct dom_sid *sid,
2570 const struct lsa_RightSet *rights)
2572 const char *sidstr, *sidndrstr;
2573 struct ldb_message *msg;
2574 struct ldb_message_element *el;
2577 struct lsa_EnumAccountRights r2;
2580 if (security_session_user_level(dce_call->conn->auth_state.session_info) <
2581 SECURITY_ADMINISTRATOR) {
2582 DEBUG(0,("lsa_AddRemoveAccount refused for supplied security token\n"));
2583 return NT_STATUS_ACCESS_DENIED;
2586 msg = ldb_msg_new(mem_ctx);
2588 return NT_STATUS_NO_MEMORY;
2591 sidndrstr = ldap_encode_ndr_dom_sid(msg, sid);
2592 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sidndrstr, msg);
2594 sidstr = dom_sid_string(msg, sid);
2595 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sidstr, msg);
2597 dnstr = talloc_asprintf(msg, "sid=%s", sidstr);
2598 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(dnstr, msg);
2600 msg->dn = ldb_dn_new(msg, state->pdb, dnstr);
2601 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(msg->dn, msg);
2603 if (ldb_flag == LDB_FLAG_MOD_ADD) {
2606 r2.in.handle = &state->handle->wire_handle;
2608 r2.out.rights = talloc(mem_ctx, struct lsa_RightSet);
2610 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
2611 if (!NT_STATUS_IS_OK(status)) {
2612 ZERO_STRUCTP(r2.out.rights);
2616 for (i=0;i<rights->count;i++) {
2617 if (sec_privilege_id(rights->names[i].string) == -1) {
2619 return NT_STATUS_NO_SUCH_PRIVILEGE;
2622 if (ldb_flag == LDB_FLAG_MOD_ADD) {
2624 for (j=0;j<r2.out.rights->count;j++) {
2625 if (strcasecmp_m(r2.out.rights->names[j].string,
2626 rights->names[i].string) == 0) {
2630 if (j != r2.out.rights->count) continue;
2633 ret = ldb_msg_add_string(msg, "privilege", rights->names[i].string);
2634 if (ret != LDB_SUCCESS) {
2636 return NT_STATUS_NO_MEMORY;
2640 el = ldb_msg_find_element(msg, "privilege");
2643 return NT_STATUS_OK;
2646 el->flags = ldb_flag;
2648 ret = ldb_modify(state->pdb, msg);
2649 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
2650 if (samdb_msg_add_dom_sid(state->pdb, msg, msg, "objectSid", sid) != LDB_SUCCESS) {
2652 return NT_STATUS_NO_MEMORY;
2654 samdb_msg_add_string(state->pdb, msg, msg, "comment", "added via LSA");
2655 ret = ldb_add(state->pdb, msg);
2657 if (ret != LDB_SUCCESS) {
2658 if (ldb_flag == LDB_FLAG_MOD_DELETE && ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
2660 return NT_STATUS_OK;
2662 DEBUG(3, ("Could not %s attributes from %s: %s",
2663 ldb_flag == LDB_FLAG_MOD_DELETE ? "delete" : "add",
2664 ldb_dn_get_linearized(msg->dn), ldb_errstring(state->pdb)));
2666 return NT_STATUS_UNEXPECTED_IO_ERROR;
2670 return NT_STATUS_OK;
2674 lsa_AddPrivilegesToAccount
2676 static NTSTATUS dcesrv_lsa_AddPrivilegesToAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2677 struct lsa_AddPrivilegesToAccount *r)
2679 struct lsa_RightSet rights;
2680 struct dcesrv_handle *h;
2681 struct lsa_account_state *astate;
2684 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2688 rights.count = r->in.privs->count;
2689 rights.names = talloc_array(mem_ctx, struct lsa_StringLarge, rights.count);
2690 if (rights.names == NULL) {
2691 return NT_STATUS_NO_MEMORY;
2693 for (i=0;i<rights.count;i++) {
2694 int id = r->in.privs->set[i].luid.low;
2695 if (r->in.privs->set[i].luid.high) {
2696 return NT_STATUS_NO_SUCH_PRIVILEGE;
2698 rights.names[i].string = sec_privilege_name(id);
2699 if (rights.names[i].string == NULL) {
2700 return NT_STATUS_NO_SUCH_PRIVILEGE;
2704 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
2705 LDB_FLAG_MOD_ADD, astate->account_sid,
2711 lsa_RemovePrivilegesFromAccount
2713 static NTSTATUS dcesrv_lsa_RemovePrivilegesFromAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2714 struct lsa_RemovePrivilegesFromAccount *r)
2716 struct lsa_RightSet *rights;
2717 struct dcesrv_handle *h;
2718 struct lsa_account_state *astate;
2721 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2725 rights = talloc(mem_ctx, struct lsa_RightSet);
2727 if (r->in.remove_all == 1 &&
2728 r->in.privs == NULL) {
2729 struct lsa_EnumAccountRights r2;
2732 r2.in.handle = &astate->policy->handle->wire_handle;
2733 r2.in.sid = astate->account_sid;
2734 r2.out.rights = rights;
2736 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
2737 if (!NT_STATUS_IS_OK(status)) {
2741 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
2742 LDB_FLAG_MOD_DELETE, astate->account_sid,
2746 if (r->in.remove_all != 0) {
2747 return NT_STATUS_INVALID_PARAMETER;
2750 rights->count = r->in.privs->count;
2751 rights->names = talloc_array(mem_ctx, struct lsa_StringLarge, rights->count);
2752 if (rights->names == NULL) {
2753 return NT_STATUS_NO_MEMORY;
2755 for (i=0;i<rights->count;i++) {
2756 int id = r->in.privs->set[i].luid.low;
2757 if (r->in.privs->set[i].luid.high) {
2758 return NT_STATUS_NO_SUCH_PRIVILEGE;
2760 rights->names[i].string = sec_privilege_name(id);
2761 if (rights->names[i].string == NULL) {
2762 return NT_STATUS_NO_SUCH_PRIVILEGE;
2766 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
2767 LDB_FLAG_MOD_DELETE, astate->account_sid,
2773 lsa_GetQuotasForAccount
2775 static NTSTATUS dcesrv_lsa_GetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2776 struct lsa_GetQuotasForAccount *r)
2778 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2783 lsa_SetQuotasForAccount
2785 static NTSTATUS dcesrv_lsa_SetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2786 struct lsa_SetQuotasForAccount *r)
2788 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2793 lsa_GetSystemAccessAccount
2795 static NTSTATUS dcesrv_lsa_GetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2796 struct lsa_GetSystemAccessAccount *r)
2800 struct lsa_EnumPrivsAccount enumPrivs;
2801 struct lsa_PrivilegeSet *privs;
2803 privs = talloc(mem_ctx, struct lsa_PrivilegeSet);
2805 return NT_STATUS_NO_MEMORY;
2811 enumPrivs.in.handle = r->in.handle;
2812 enumPrivs.out.privs = &privs;
2814 status = dcesrv_lsa_EnumPrivsAccount(dce_call, mem_ctx, &enumPrivs);
2815 if (!NT_STATUS_IS_OK(status)) {
2819 *(r->out.access_mask) = 0x00000000;
2821 for (i = 0; i < privs->count; i++) {
2822 int priv = privs->set[i].luid.low;
2825 case SEC_PRIV_INTERACTIVE_LOGON:
2826 *(r->out.access_mask) |= LSA_POLICY_MODE_INTERACTIVE;
2828 case SEC_PRIV_NETWORK_LOGON:
2829 *(r->out.access_mask) |= LSA_POLICY_MODE_NETWORK;
2831 case SEC_PRIV_REMOTE_INTERACTIVE_LOGON:
2832 *(r->out.access_mask) |= LSA_POLICY_MODE_REMOTE_INTERACTIVE;
2837 return NT_STATUS_OK;
2842 lsa_SetSystemAccessAccount
2844 static NTSTATUS dcesrv_lsa_SetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2845 struct lsa_SetSystemAccessAccount *r)
2847 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2854 static NTSTATUS dcesrv_lsa_CreateSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2855 struct lsa_CreateSecret *r)
2857 struct dcesrv_handle *policy_handle;
2858 struct lsa_policy_state *policy_state;
2859 struct lsa_secret_state *secret_state;
2860 struct dcesrv_handle *handle;
2861 struct ldb_message **msgs, *msg;
2862 const char *attrs[] = {
2870 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2871 ZERO_STRUCTP(r->out.sec_handle);
2873 switch (security_session_user_level(dce_call->conn->auth_state.session_info))
2875 case SECURITY_SYSTEM:
2876 case SECURITY_ADMINISTRATOR:
2879 /* Users and annonymous are not allowed create secrets */
2880 return NT_STATUS_ACCESS_DENIED;
2883 policy_state = policy_handle->data;
2885 if (!r->in.name.string) {
2886 return NT_STATUS_INVALID_PARAMETER;
2889 secret_state = talloc(mem_ctx, struct lsa_secret_state);
2890 if (!secret_state) {
2891 return NT_STATUS_NO_MEMORY;
2893 secret_state->policy = policy_state;
2895 msg = ldb_msg_new(mem_ctx);
2897 return NT_STATUS_NO_MEMORY;
2900 if (strncmp("G$", r->in.name.string, 2) == 0) {
2902 name = &r->in.name.string[2];
2903 /* 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) */
2904 secret_state->sam_ldb = talloc_reference(secret_state,
2905 samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(dce_call->conn->dce_ctx->lp_ctx)));
2906 secret_state->global = true;
2908 if (strlen(name) < 1) {
2909 return NT_STATUS_INVALID_PARAMETER;
2912 name2 = talloc_asprintf(mem_ctx, "%s Secret", ldb_binary_encode_string(mem_ctx, name));
2913 /* search for the secret record */
2914 ret = gendb_search(secret_state->sam_ldb,
2915 mem_ctx, policy_state->system_dn, &msgs, attrs,
2916 "(&(cn=%s)(objectclass=secret))",
2919 return NT_STATUS_OBJECT_NAME_COLLISION;
2923 DEBUG(0,("Failure searching for CN=%s: %s\n",
2924 name2, ldb_errstring(secret_state->sam_ldb)));
2925 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2928 msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
2929 if (!name2 || ! ldb_dn_add_child_fmt(msg->dn, "cn=%s", name2)) {
2930 return NT_STATUS_NO_MEMORY;
2933 samdb_msg_add_string(secret_state->sam_ldb, mem_ctx, msg, "cn", name2);
2936 secret_state->global = false;
2938 name = r->in.name.string;
2939 if (strlen(name) < 1) {
2940 return NT_STATUS_INVALID_PARAMETER;
2943 secret_state->sam_ldb = talloc_reference(secret_state,
2944 secrets_db_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx));
2945 /* search for the secret record */
2946 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
2947 ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
2949 "(&(cn=%s)(objectclass=secret))",
2950 ldb_binary_encode_string(mem_ctx, name));
2952 return NT_STATUS_OBJECT_NAME_COLLISION;
2956 DEBUG(0,("Failure searching for CN=%s: %s\n",
2957 name, ldb_errstring(secret_state->sam_ldb)));
2958 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2961 msg->dn = ldb_dn_new_fmt(mem_ctx, secret_state->sam_ldb, "cn=%s,cn=LSA Secrets", name);
2962 samdb_msg_add_string(secret_state->sam_ldb, mem_ctx, msg, "cn", name);
2965 samdb_msg_add_string(secret_state->sam_ldb, mem_ctx, msg, "objectClass", "secret");
2967 secret_state->secret_dn = talloc_reference(secret_state, msg->dn);
2969 /* create the secret */
2970 ret = ldb_add(secret_state->sam_ldb, msg);
2971 if (ret != LDB_SUCCESS) {
2972 DEBUG(0,("Failed to create secret record %s: %s\n",
2973 ldb_dn_get_linearized(msg->dn),
2974 ldb_errstring(secret_state->sam_ldb)));
2975 return NT_STATUS_ACCESS_DENIED;
2978 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
2980 return NT_STATUS_NO_MEMORY;
2983 handle->data = talloc_steal(handle, secret_state);
2985 secret_state->access_mask = r->in.access_mask;
2986 secret_state->policy = talloc_reference(secret_state, policy_state);
2988 *r->out.sec_handle = handle->wire_handle;
2990 return NT_STATUS_OK;
2997 static NTSTATUS dcesrv_lsa_OpenSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2998 struct lsa_OpenSecret *r)
3000 struct dcesrv_handle *policy_handle;
3002 struct lsa_policy_state *policy_state;
3003 struct lsa_secret_state *secret_state;
3004 struct dcesrv_handle *handle;
3005 struct ldb_message **msgs;
3006 const char *attrs[] = {
3014 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
3015 ZERO_STRUCTP(r->out.sec_handle);
3016 policy_state = policy_handle->data;
3018 if (!r->in.name.string) {
3019 return NT_STATUS_INVALID_PARAMETER;
3022 switch (security_session_user_level(dce_call->conn->auth_state.session_info))
3024 case SECURITY_SYSTEM:
3025 case SECURITY_ADMINISTRATOR:
3028 /* Users and annonymous are not allowed to access secrets */
3029 return NT_STATUS_ACCESS_DENIED;
3032 secret_state = talloc(mem_ctx, struct lsa_secret_state);
3033 if (!secret_state) {
3034 return NT_STATUS_NO_MEMORY;
3036 secret_state->policy = policy_state;
3038 if (strncmp("G$", r->in.name.string, 2) == 0) {
3039 name = &r->in.name.string[2];
3040 /* 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) */
3041 secret_state->sam_ldb = talloc_reference(secret_state,
3042 samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(dce_call->conn->dce_ctx->lp_ctx)));
3043 secret_state->global = true;
3045 if (strlen(name) < 1) {
3046 return NT_STATUS_INVALID_PARAMETER;
3049 /* search for the secret record */
3050 ret = gendb_search(secret_state->sam_ldb,
3051 mem_ctx, policy_state->system_dn, &msgs, attrs,
3052 "(&(cn=%s Secret)(objectclass=secret))",
3053 ldb_binary_encode_string(mem_ctx, name));
3055 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3059 DEBUG(0,("Found %d records matching DN %s\n", ret,
3060 ldb_dn_get_linearized(policy_state->system_dn)));
3061 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3065 secret_state->global = false;
3066 secret_state->sam_ldb = talloc_reference(secret_state,
3067 secrets_db_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx));
3069 name = r->in.name.string;
3070 if (strlen(name) < 1) {
3071 return NT_STATUS_INVALID_PARAMETER;
3074 /* search for the secret record */
3075 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
3076 ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
3078 "(&(cn=%s)(objectclass=secret))",
3079 ldb_binary_encode_string(mem_ctx, name));
3081 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3085 DEBUG(0,("Found %d records matching CN=%s\n",
3086 ret, ldb_binary_encode_string(mem_ctx, name)));
3087 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3091 secret_state->secret_dn = talloc_reference(secret_state, msgs[0]->dn);
3093 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
3095 return NT_STATUS_NO_MEMORY;
3098 handle->data = talloc_steal(handle, secret_state);
3100 secret_state->access_mask = r->in.access_mask;
3101 secret_state->policy = talloc_reference(secret_state, policy_state);
3103 *r->out.sec_handle = handle->wire_handle;
3105 return NT_STATUS_OK;
3112 static NTSTATUS dcesrv_lsa_SetSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3113 struct lsa_SetSecret *r)
3116 struct dcesrv_handle *h;
3117 struct lsa_secret_state *secret_state;
3118 struct ldb_message *msg;
3119 DATA_BLOB session_key;
3120 DATA_BLOB crypt_secret, secret;
3123 NTSTATUS status = NT_STATUS_OK;
3125 struct timeval now = timeval_current();
3126 NTTIME nt_now = timeval_to_nttime(&now);
3128 DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3130 secret_state = h->data;
3132 msg = ldb_msg_new(mem_ctx);
3134 return NT_STATUS_NO_MEMORY;
3137 msg->dn = talloc_reference(mem_ctx, secret_state->secret_dn);
3139 return NT_STATUS_NO_MEMORY;
3141 status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
3142 if (!NT_STATUS_IS_OK(status)) {
3146 if (r->in.old_val) {
3148 crypt_secret.data = r->in.old_val->data;
3149 crypt_secret.length = r->in.old_val->size;
3151 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3152 if (!NT_STATUS_IS_OK(status)) {
3156 val.data = secret.data;
3157 val.length = secret.length;
3160 if (samdb_msg_add_value(secret_state->sam_ldb,
3161 mem_ctx, msg, "priorValue", &val) != LDB_SUCCESS) {
3162 return NT_STATUS_NO_MEMORY;
3165 /* set old value mtime */
3166 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3167 mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3168 return NT_STATUS_NO_MEMORY;
3172 /* If the old value is not set, then migrate the
3173 * current value to the old value */
3174 const struct ldb_val *old_val;
3175 NTTIME last_set_time;
3176 struct ldb_message **res;
3177 const char *attrs[] = {
3183 /* search for the secret record */
3184 ret = gendb_search_dn(secret_state->sam_ldb,mem_ctx,
3185 secret_state->secret_dn, &res, attrs);
3187 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3191 DEBUG(0,("Found %d records matching dn=%s\n", ret,
3192 ldb_dn_get_linearized(secret_state->secret_dn)));
3193 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3196 old_val = ldb_msg_find_ldb_val(res[0], "currentValue");
3197 last_set_time = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
3201 if (samdb_msg_add_value(secret_state->sam_ldb,
3202 mem_ctx, msg, "priorValue",
3204 return NT_STATUS_NO_MEMORY;
3207 if (samdb_msg_add_delete(secret_state->sam_ldb,
3208 mem_ctx, msg, "priorValue")) {
3209 return NT_STATUS_NO_MEMORY;
3214 /* set old value mtime */
3215 if (ldb_msg_find_ldb_val(res[0], "lastSetTime")) {
3216 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3217 mem_ctx, msg, "priorSetTime", last_set_time) != LDB_SUCCESS) {
3218 return NT_STATUS_NO_MEMORY;
3221 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3222 mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3223 return NT_STATUS_NO_MEMORY;
3228 if (r->in.new_val) {
3230 crypt_secret.data = r->in.new_val->data;
3231 crypt_secret.length = r->in.new_val->size;
3233 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3234 if (!NT_STATUS_IS_OK(status)) {
3238 val.data = secret.data;
3239 val.length = secret.length;
3242 if (samdb_msg_add_value(secret_state->sam_ldb,
3243 mem_ctx, msg, "currentValue", &val) != LDB_SUCCESS) {
3244 return NT_STATUS_NO_MEMORY;
3247 /* set new value mtime */
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;
3254 /* NULL out the NEW value */
3255 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3256 mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3257 return NT_STATUS_NO_MEMORY;
3259 if (samdb_msg_add_delete(secret_state->sam_ldb,
3260 mem_ctx, msg, "currentValue") != LDB_SUCCESS) {
3261 return NT_STATUS_NO_MEMORY;
3265 /* modify the samdb record */
3266 ret = dsdb_replace(secret_state->sam_ldb, msg, 0);
3267 if (ret != LDB_SUCCESS) {
3268 /* we really need samdb.c to return NTSTATUS */
3269 return NT_STATUS_UNSUCCESSFUL;
3272 return NT_STATUS_OK;
3279 static NTSTATUS dcesrv_lsa_QuerySecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3280 struct lsa_QuerySecret *r)
3282 struct dcesrv_handle *h;
3283 struct lsa_secret_state *secret_state;
3284 struct ldb_message *msg;
3285 DATA_BLOB session_key;
3286 DATA_BLOB crypt_secret, secret;
3288 struct ldb_message **res;
3289 const char *attrs[] = {
3299 DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3301 /* Ensure user is permitted to read this... */
3302 switch (security_session_user_level(dce_call->conn->auth_state.session_info))
3304 case SECURITY_SYSTEM:
3305 case SECURITY_ADMINISTRATOR:
3308 /* Users and annonymous are not allowed to read secrets */
3309 return NT_STATUS_ACCESS_DENIED;
3312 secret_state = h->data;
3314 /* pull all the user attributes */
3315 ret = gendb_search_dn(secret_state->sam_ldb, mem_ctx,
3316 secret_state->secret_dn, &res, attrs);
3318 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3322 nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
3323 if (!NT_STATUS_IS_OK(nt_status)) {
3327 if (r->in.old_val) {
3328 const struct ldb_val *prior_val;
3329 r->out.old_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3330 if (!r->out.old_val) {
3331 return NT_STATUS_NO_MEMORY;
3333 prior_val = ldb_msg_find_ldb_val(res[0], "priorValue");
3335 if (prior_val && prior_val->length) {
3336 secret.data = prior_val->data;
3337 secret.length = prior_val->length;
3340 crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3341 if (!crypt_secret.length) {
3342 return NT_STATUS_NO_MEMORY;
3344 r->out.old_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3345 if (!r->out.old_val->buf) {
3346 return NT_STATUS_NO_MEMORY;
3348 r->out.old_val->buf->size = crypt_secret.length;
3349 r->out.old_val->buf->length = crypt_secret.length;
3350 r->out.old_val->buf->data = crypt_secret.data;
3354 if (r->in.old_mtime) {
3355 r->out.old_mtime = talloc(mem_ctx, NTTIME);
3356 if (!r->out.old_mtime) {
3357 return NT_STATUS_NO_MEMORY;
3359 *r->out.old_mtime = ldb_msg_find_attr_as_uint64(res[0], "priorSetTime", 0);
3362 if (r->in.new_val) {
3363 const struct ldb_val *new_val;
3364 r->out.new_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3365 if (!r->out.new_val) {
3366 return NT_STATUS_NO_MEMORY;
3369 new_val = ldb_msg_find_ldb_val(res[0], "currentValue");
3371 if (new_val && new_val->length) {
3372 secret.data = new_val->data;
3373 secret.length = new_val->length;
3376 crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3377 if (!crypt_secret.length) {
3378 return NT_STATUS_NO_MEMORY;
3380 r->out.new_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3381 if (!r->out.new_val->buf) {
3382 return NT_STATUS_NO_MEMORY;
3384 r->out.new_val->buf->length = crypt_secret.length;
3385 r->out.new_val->buf->size = crypt_secret.length;
3386 r->out.new_val->buf->data = crypt_secret.data;
3390 if (r->in.new_mtime) {
3391 r->out.new_mtime = talloc(mem_ctx, NTTIME);
3392 if (!r->out.new_mtime) {
3393 return NT_STATUS_NO_MEMORY;
3395 *r->out.new_mtime = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
3398 return NT_STATUS_OK;
3405 static NTSTATUS dcesrv_lsa_LookupPrivValue(struct dcesrv_call_state *dce_call,
3406 TALLOC_CTX *mem_ctx,
3407 struct lsa_LookupPrivValue *r)
3409 struct dcesrv_handle *h;
3410 struct lsa_policy_state *state;
3413 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3417 id = sec_privilege_id(r->in.name->string);
3419 return NT_STATUS_NO_SUCH_PRIVILEGE;
3422 r->out.luid->low = id;
3423 r->out.luid->high = 0;
3425 return NT_STATUS_OK;
3432 static NTSTATUS dcesrv_lsa_LookupPrivName(struct dcesrv_call_state *dce_call,
3433 TALLOC_CTX *mem_ctx,
3434 struct lsa_LookupPrivName *r)
3436 struct dcesrv_handle *h;
3437 struct lsa_policy_state *state;
3438 struct lsa_StringLarge *name;
3439 const char *privname;
3441 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3445 if (r->in.luid->high != 0) {
3446 return NT_STATUS_NO_SUCH_PRIVILEGE;
3449 privname = sec_privilege_name(r->in.luid->low);
3450 if (privname == NULL) {
3451 return NT_STATUS_NO_SUCH_PRIVILEGE;
3454 name = talloc(mem_ctx, struct lsa_StringLarge);
3456 return NT_STATUS_NO_MEMORY;
3459 name->string = privname;
3461 *r->out.name = name;
3463 return NT_STATUS_OK;
3468 lsa_LookupPrivDisplayName
3470 static NTSTATUS dcesrv_lsa_LookupPrivDisplayName(struct dcesrv_call_state *dce_call,
3471 TALLOC_CTX *mem_ctx,
3472 struct lsa_LookupPrivDisplayName *r)
3474 struct dcesrv_handle *h;
3475 struct lsa_policy_state *state;
3476 struct lsa_StringLarge *disp_name = NULL;
3479 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3483 id = sec_privilege_id(r->in.name->string);
3485 return NT_STATUS_NO_SUCH_PRIVILEGE;
3488 disp_name = talloc(mem_ctx, struct lsa_StringLarge);
3489 if (disp_name == NULL) {
3490 return NT_STATUS_NO_MEMORY;
3493 disp_name->string = sec_privilege_display_name(id, &r->in.language_id);
3494 if (disp_name->string == NULL) {
3495 return NT_STATUS_INTERNAL_ERROR;
3498 *r->out.disp_name = disp_name;
3499 *r->out.returned_language_id = 0;
3501 return NT_STATUS_OK;
3506 lsa_EnumAccountsWithUserRight
3508 static NTSTATUS dcesrv_lsa_EnumAccountsWithUserRight(struct dcesrv_call_state *dce_call,
3509 TALLOC_CTX *mem_ctx,
3510 struct lsa_EnumAccountsWithUserRight *r)
3512 struct dcesrv_handle *h;
3513 struct lsa_policy_state *state;
3515 struct ldb_message **res;
3516 const char * const attrs[] = { "objectSid", NULL};
3517 const char *privname;
3519 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3523 if (r->in.name == NULL) {
3524 return NT_STATUS_NO_SUCH_PRIVILEGE;
3527 privname = r->in.name->string;
3528 if (sec_privilege_id(privname) == -1) {
3529 return NT_STATUS_NO_SUCH_PRIVILEGE;
3532 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
3533 "privilege=%s", privname);
3535 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3538 return NT_STATUS_NO_MORE_ENTRIES;
3541 r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, ret);
3542 if (r->out.sids->sids == NULL) {
3543 return NT_STATUS_NO_MEMORY;
3545 for (i=0;i<ret;i++) {
3546 r->out.sids->sids[i].sid = samdb_result_dom_sid(r->out.sids->sids,
3547 res[i], "objectSid");
3548 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
3550 r->out.sids->num_sids = ret;
3552 return NT_STATUS_OK;
3557 lsa_AddAccountRights
3559 static NTSTATUS dcesrv_lsa_AddAccountRights(struct dcesrv_call_state *dce_call,
3560 TALLOC_CTX *mem_ctx,
3561 struct lsa_AddAccountRights *r)
3563 struct dcesrv_handle *h;
3564 struct lsa_policy_state *state;
3566 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3570 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3572 r->in.sid, r->in.rights);
3577 lsa_RemoveAccountRights
3579 static NTSTATUS dcesrv_lsa_RemoveAccountRights(struct dcesrv_call_state *dce_call,
3580 TALLOC_CTX *mem_ctx,
3581 struct lsa_RemoveAccountRights *r)
3583 struct dcesrv_handle *h;
3584 struct lsa_policy_state *state;
3586 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3590 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3591 LDB_FLAG_MOD_DELETE,
3592 r->in.sid, r->in.rights);
3597 lsa_StorePrivateData
3599 static NTSTATUS dcesrv_lsa_StorePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3600 struct lsa_StorePrivateData *r)
3602 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3607 lsa_RetrievePrivateData
3609 static NTSTATUS dcesrv_lsa_RetrievePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3610 struct lsa_RetrievePrivateData *r)
3612 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3619 static NTSTATUS dcesrv_lsa_GetUserName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3620 struct lsa_GetUserName *r)
3622 NTSTATUS status = NT_STATUS_OK;
3623 const char *account_name;
3624 const char *authority_name;
3625 struct lsa_String *_account_name;
3626 struct lsa_String *_authority_name = NULL;
3628 /* this is what w2k3 does */
3629 r->out.account_name = r->in.account_name;
3630 r->out.authority_name = r->in.authority_name;
3632 if (r->in.account_name
3633 && *r->in.account_name
3634 /* && *(*r->in.account_name)->string */
3636 return NT_STATUS_INVALID_PARAMETER;
3639 if (r->in.authority_name
3640 && *r->in.authority_name
3641 /* && *(*r->in.authority_name)->string */
3643 return NT_STATUS_INVALID_PARAMETER;
3646 account_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->server_info->account_name);
3647 authority_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->server_info->domain_name);
3649 _account_name = talloc(mem_ctx, struct lsa_String);
3650 NT_STATUS_HAVE_NO_MEMORY(_account_name);
3651 _account_name->string = account_name;
3653 if (r->in.authority_name) {
3654 _authority_name = talloc(mem_ctx, struct lsa_String);
3655 NT_STATUS_HAVE_NO_MEMORY(_authority_name);
3656 _authority_name->string = authority_name;
3659 *r->out.account_name = _account_name;
3660 if (r->out.authority_name) {
3661 *r->out.authority_name = _authority_name;
3670 static NTSTATUS dcesrv_lsa_SetInfoPolicy2(struct dcesrv_call_state *dce_call,
3671 TALLOC_CTX *mem_ctx,
3672 struct lsa_SetInfoPolicy2 *r)
3674 /* need to support these */
3675 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3679 lsa_QueryDomainInformationPolicy
3681 static NTSTATUS dcesrv_lsa_QueryDomainInformationPolicy(struct dcesrv_call_state *dce_call,
3682 TALLOC_CTX *mem_ctx,
3683 struct lsa_QueryDomainInformationPolicy *r)
3685 union lsa_DomainInformationPolicy *info;
3687 info = talloc(r->out.info, union lsa_DomainInformationPolicy);
3689 return NT_STATUS_NO_MEMORY;
3692 switch (r->in.level) {
3693 case LSA_DOMAIN_INFO_POLICY_EFS:
3695 *r->out.info = NULL;
3696 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3697 case LSA_DOMAIN_INFO_POLICY_KERBEROS:
3699 struct lsa_DomainInfoKerberos *k = &info->kerberos_info;
3700 struct smb_krb5_context *smb_krb5_context;
3701 int ret = smb_krb5_init_context(mem_ctx,
3702 dce_call->event_ctx,
3703 dce_call->conn->dce_ctx->lp_ctx,
3707 *r->out.info = NULL;
3708 return NT_STATUS_INTERNAL_ERROR;
3710 k->enforce_restrictions = 0; /* FIXME, details missing from MS-LSAD 2.2.53 */
3711 k->service_tkt_lifetime = 0; /* Need to find somewhere to store this, and query in KDC too */
3712 k->user_tkt_lifetime = 0; /* Need to find somewhere to store this, and query in KDC too */
3713 k->user_tkt_renewaltime = 0; /* Need to find somewhere to store this, and query in KDC too */
3714 k->clock_skew = krb5_get_max_time_skew(smb_krb5_context->krb5_context);
3715 talloc_free(smb_krb5_context);
3716 *r->out.info = info;
3717 return NT_STATUS_OK;
3721 *r->out.info = NULL;
3722 return NT_STATUS_INVALID_INFO_CLASS;
3727 lsa_SetDomInfoPolicy
3729 static NTSTATUS dcesrv_lsa_SetDomainInformationPolicy(struct dcesrv_call_state *dce_call,
3730 TALLOC_CTX *mem_ctx,
3731 struct lsa_SetDomainInformationPolicy *r)
3733 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3739 static NTSTATUS dcesrv_lsa_TestCall(struct dcesrv_call_state *dce_call,
3740 TALLOC_CTX *mem_ctx,
3741 struct lsa_TestCall *r)
3743 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3749 static NTSTATUS dcesrv_lsa_CREDRWRITE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3750 struct lsa_CREDRWRITE *r)
3752 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3759 static NTSTATUS dcesrv_lsa_CREDRREAD(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3760 struct lsa_CREDRREAD *r)
3762 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3769 static NTSTATUS dcesrv_lsa_CREDRENUMERATE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3770 struct lsa_CREDRENUMERATE *r)
3772 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3777 lsa_CREDRWRITEDOMAINCREDENTIALS
3779 static NTSTATUS dcesrv_lsa_CREDRWRITEDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3780 struct lsa_CREDRWRITEDOMAINCREDENTIALS *r)
3782 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3787 lsa_CREDRREADDOMAINCREDENTIALS
3789 static NTSTATUS dcesrv_lsa_CREDRREADDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3790 struct lsa_CREDRREADDOMAINCREDENTIALS *r)
3792 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3799 static NTSTATUS dcesrv_lsa_CREDRDELETE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3800 struct lsa_CREDRDELETE *r)
3802 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3807 lsa_CREDRGETTARGETINFO
3809 static NTSTATUS dcesrv_lsa_CREDRGETTARGETINFO(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3810 struct lsa_CREDRGETTARGETINFO *r)
3812 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3817 lsa_CREDRPROFILELOADED
3819 static NTSTATUS dcesrv_lsa_CREDRPROFILELOADED(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3820 struct lsa_CREDRPROFILELOADED *r)
3822 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3827 lsa_CREDRGETSESSIONTYPES
3829 static NTSTATUS dcesrv_lsa_CREDRGETSESSIONTYPES(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3830 struct lsa_CREDRGETSESSIONTYPES *r)
3832 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3837 lsa_LSARREGISTERAUDITEVENT
3839 static NTSTATUS dcesrv_lsa_LSARREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3840 struct lsa_LSARREGISTERAUDITEVENT *r)
3842 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3847 lsa_LSARGENAUDITEVENT
3849 static NTSTATUS dcesrv_lsa_LSARGENAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3850 struct lsa_LSARGENAUDITEVENT *r)
3852 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3857 lsa_LSARUNREGISTERAUDITEVENT
3859 static NTSTATUS dcesrv_lsa_LSARUNREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3860 struct lsa_LSARUNREGISTERAUDITEVENT *r)
3862 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3867 lsa_lsaRQueryForestTrustInformation
3869 static NTSTATUS dcesrv_lsa_lsaRQueryForestTrustInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3870 struct lsa_lsaRQueryForestTrustInformation *r)
3872 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3875 #define DNS_CMP_MATCH 0
3876 #define DNS_CMP_FIRST_IS_CHILD 1
3877 #define DNS_CMP_SECOND_IS_CHILD 2
3878 #define DNS_CMP_NO_MATCH 3
3880 /* this function assumes names are well formed DNS names.
3881 * it doesn't validate them */
3882 static int dns_cmp(const char *s1, size_t l1,
3883 const char *s2, size_t l2)
3885 const char *p1, *p2;
3890 if (strcasecmp_m(s1, s2) == 0) {
3891 return DNS_CMP_MATCH;
3893 return DNS_CMP_NO_MATCH;
3901 cret = DNS_CMP_FIRST_IS_CHILD;
3907 cret = DNS_CMP_SECOND_IS_CHILD;
3910 if (p1[t1 - t2 - 1] != '.') {
3911 return DNS_CMP_NO_MATCH;
3914 if (strcasecmp_m(&p1[t1 - t2], p2) == 0) {
3918 return DNS_CMP_NO_MATCH;
3921 /* decode all TDOs forest trust info blobs */
3922 static NTSTATUS get_ft_info(TALLOC_CTX *mem_ctx,
3923 struct smb_iconv_convenience *ic,
3924 struct ldb_message *msg,
3925 struct ForestTrustInfo *info)
3927 const struct ldb_val *ft_blob;
3928 enum ndr_err_code ndr_err;
3930 ft_blob = ldb_msg_find_ldb_val(msg, "msDS-TrustForestTrustInfo");
3931 if (!ft_blob || !ft_blob->data) {
3932 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3934 /* ldb_val is equivalent to DATA_BLOB */
3935 ndr_err = ndr_pull_struct_blob_all(ft_blob, mem_ctx, ic,
3937 (ndr_pull_flags_fn_t)ndr_pull_ForestTrustInfo);
3938 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
3939 return NT_STATUS_INVALID_DOMAIN_STATE;
3942 return NT_STATUS_OK;
3945 static NTSTATUS own_ft_info(struct lsa_policy_state *ps,
3946 struct ForestTrustInfo *fti)
3948 struct ForestTrustDataDomainInfo *info;
3949 struct ForestTrustInfoRecord *rec;
3953 fti->records = talloc_array(fti,
3954 struct ForestTrustInfoRecordArmor, 2);
3955 if (!fti->records) {
3956 return NT_STATUS_NO_MEMORY;
3960 rec = &fti->records[0].record;
3964 rec->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
3966 rec->data.name.string = talloc_strdup(fti, ps->forest_dns);
3967 if (!rec->data.name.string) {
3968 return NT_STATUS_NO_MEMORY;
3970 rec->data.name.size = strlen(rec->data.name.string);
3973 rec = &fti->records[1].record;
3977 rec->type = LSA_FOREST_TRUST_DOMAIN_INFO;
3979 info = &rec->data.info;
3981 info->sid = *ps->domain_sid;
3982 info->dns_name.string = talloc_strdup(fti, ps->domain_dns);
3983 if (!info->dns_name.string) {
3984 return NT_STATUS_NO_MEMORY;
3986 info->dns_name.size = strlen(info->dns_name.string);
3987 info->netbios_name.string = talloc_strdup(fti, ps->domain_name);
3988 if (!info->netbios_name.string) {
3989 return NT_STATUS_NO_MEMORY;
3991 info->netbios_name.size = strlen(info->netbios_name.string);
3993 return NT_STATUS_OK;
3996 static NTSTATUS make_ft_info(TALLOC_CTX *mem_ctx,
3997 struct lsa_ForestTrustInformation *lfti,
3998 struct ForestTrustInfo *fti)
4000 struct lsa_ForestTrustRecord *lrec;
4001 struct ForestTrustInfoRecord *rec;
4002 struct lsa_StringLarge *tln;
4003 struct lsa_ForestTrustDomainInfo *info;
4007 fti->count = lfti->count;
4008 fti->records = talloc_array(mem_ctx,
4009 struct ForestTrustInfoRecordArmor,
4011 if (!fti->records) {
4012 return NT_STATUS_NO_MEMORY;
4014 for (i = 0; i < fti->count; i++) {
4015 lrec = lfti->entries[i];
4016 rec = &fti->records[i].record;
4018 rec->flags = lrec->flags;
4019 rec->timestamp = lrec->time;
4020 rec->type = lrec->type;
4022 switch (lrec->type) {
4023 case LSA_FOREST_TRUST_TOP_LEVEL_NAME:
4024 case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
4025 tln = &lrec->forest_trust_data.top_level_name;
4026 rec->data.name.string =
4027 talloc_strdup(mem_ctx, tln->string);
4028 if (!rec->data.name.string) {
4029 return NT_STATUS_NO_MEMORY;
4031 rec->data.name.size = strlen(rec->data.name.string);
4033 case LSA_FOREST_TRUST_DOMAIN_INFO:
4034 info = &lrec->forest_trust_data.domain_info;
4035 rec->data.info.sid = *info->domain_sid;
4036 rec->data.info.dns_name.string =
4037 talloc_strdup(mem_ctx,
4038 info->dns_domain_name.string);
4039 if (!rec->data.info.dns_name.string) {
4040 return NT_STATUS_NO_MEMORY;
4042 rec->data.info.dns_name.size =
4043 strlen(rec->data.info.dns_name.string);
4044 rec->data.info.netbios_name.string =
4045 talloc_strdup(mem_ctx,
4046 info->netbios_domain_name.string);
4047 if (!rec->data.info.netbios_name.string) {
4048 return NT_STATUS_NO_MEMORY;
4050 rec->data.info.netbios_name.size =
4051 strlen(rec->data.info.netbios_name.string);
4054 return NT_STATUS_INVALID_DOMAIN_STATE;
4058 return NT_STATUS_OK;
4061 static NTSTATUS add_collision(struct lsa_ForestTrustCollisionInfo *c_info,
4062 uint32_t index, uint32_t collision_type,
4063 uint32_t conflict_type, const char *tdo_name);
4065 static NTSTATUS check_ft_info(TALLOC_CTX *mem_ctx,
4066 const char *tdo_name,
4067 struct ForestTrustInfo *tdo_fti,
4068 struct ForestTrustInfo *new_fti,
4069 struct lsa_ForestTrustCollisionInfo *c_info)
4071 struct ForestTrustInfoRecord *nrec;
4072 struct ForestTrustInfoRecord *trec;
4073 const char *dns_name;
4074 const char *nb_name;
4075 struct dom_sid *sid;
4081 uint32_t new_fti_idx;
4083 /* use always TDO type, until we understand when Xref can be used */
4084 uint32_t collision_type = LSA_FOREST_TRUST_COLLISION_TDO;
4092 for (new_fti_idx = 0; new_fti_idx < new_fti->count; new_fti_idx++) {
4094 nrec = &new_fti->records[new_fti_idx].record;
4096 tln_conflict = false;
4097 sid_conflict = false;
4098 nb_conflict = false;
4101 switch (nrec->type) {
4102 case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
4103 /* exclusions do not conflict by definition */
4106 case FOREST_TRUST_TOP_LEVEL_NAME:
4107 dns_name = nrec->data.name.string;
4108 dns_len = nrec->data.name.size;
4111 case LSA_FOREST_TRUST_DOMAIN_INFO:
4112 dns_name = nrec->data.info.dns_name.string;
4113 dns_len = nrec->data.info.dns_name.size;
4114 nb_name = nrec->data.info.netbios_name.string;
4115 nb_len = nrec->data.info.netbios_name.size;
4116 sid = &nrec->data.info.sid;
4120 if (!dns_name) continue;
4122 /* check if this is already taken and not excluded */
4123 for (i = 0; i < tdo_fti->count; i++) {
4124 trec = &tdo_fti->records[i].record;
4126 switch (trec->type) {
4127 case FOREST_TRUST_TOP_LEVEL_NAME:
4129 tname = trec->data.name.string;
4130 tlen = trec->data.name.size;
4132 case FOREST_TRUST_TOP_LEVEL_NAME_EX:
4134 tname = trec->data.name.string;
4135 tlen = trec->data.name.size;
4137 case FOREST_TRUST_DOMAIN_INFO:
4139 tname = trec->data.info.dns_name.string;
4140 tlen = trec->data.info.dns_name.size;
4142 ret = dns_cmp(dns_name, dns_len, tname, tlen);
4145 /* if it matches exclusion,
4146 * it doesn't conflict */
4152 case DNS_CMP_FIRST_IS_CHILD:
4153 case DNS_CMP_SECOND_IS_CHILD:
4154 tln_conflict = true;
4160 /* explicit exclusion, no dns name conflict here */
4162 tln_conflict = false;
4165 if (nrec->type != FOREST_TRUST_DOMAIN_INFO) {
4169 /* also test for domain info */
4170 if (!(trec->flags & LSA_SID_DISABLED_ADMIN) &&
4171 dom_sid_compare(&trec->data.info.sid, sid) == 0) {
4172 sid_conflict = true;
4174 if (!(trec->flags & LSA_NB_DISABLED_ADMIN) &&
4175 strcasecmp_m(trec->data.info.netbios_name.string,
4182 nt_status = add_collision(c_info, new_fti_idx,
4184 LSA_TLN_DISABLED_CONFLICT,
4188 nt_status = add_collision(c_info, new_fti_idx,
4190 LSA_SID_DISABLED_CONFLICT,
4194 nt_status = add_collision(c_info, new_fti_idx,
4196 LSA_NB_DISABLED_CONFLICT,
4201 return NT_STATUS_OK;
4204 static NTSTATUS add_collision(struct lsa_ForestTrustCollisionInfo *c_info,
4205 uint32_t idx, uint32_t collision_type,
4206 uint32_t conflict_type, const char *tdo_name)
4208 struct lsa_ForestTrustCollisionRecord **es;
4209 uint32_t i = c_info->count;
4211 es = talloc_realloc(c_info, c_info->entries,
4212 struct lsa_ForestTrustCollisionRecord *, i + 1);
4214 return NT_STATUS_NO_MEMORY;
4216 c_info->entries = es;
4217 c_info->count = i + 1;
4219 es[i] = talloc(es, struct lsa_ForestTrustCollisionRecord);
4221 return NT_STATUS_NO_MEMORY;
4225 es[i]->type = collision_type;
4226 es[i]->flags.flags = conflict_type;
4227 es[i]->name.string = talloc_strdup(es[i], tdo_name);
4228 if (!es[i]->name.string) {
4229 return NT_STATUS_NO_MEMORY;
4231 es[i]->name.size = strlen(es[i]->name.string);
4233 return NT_STATUS_OK;
4237 lsa_lsaRSetForestTrustInformation
4239 static NTSTATUS dcesrv_lsa_lsaRSetForestTrustInformation(struct dcesrv_call_state *dce_call,
4240 TALLOC_CTX *mem_ctx,
4241 struct lsa_lsaRSetForestTrustInformation *r)
4243 struct dcesrv_handle *h;
4244 struct lsa_policy_state *p_state;
4245 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
4246 struct smb_iconv_convenience *ic = lp_iconv_convenience(lp_ctx);
4247 const char *trust_attrs[] = { "trustPartner", "trustAttributes",
4248 "msDS-TrustForestTrustInfo", NULL };
4249 struct ldb_message **dom_res = NULL;
4250 struct ldb_dn *tdo_dn;
4251 struct ldb_message *msg;
4253 const char *td_name;
4254 uint32_t trust_attributes;
4255 struct lsa_ForestTrustCollisionInfo *c_info;
4256 struct ForestTrustInfo *nfti;
4257 struct ForestTrustInfo *fti;
4259 enum ndr_err_code ndr_err;
4263 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
4267 if (strcmp(p_state->domain_dns, p_state->forest_dns)) {
4268 return NT_STATUS_INVALID_DOMAIN_STATE;
4271 /* abort if we are not a PDC */
4272 if (!samdb_is_pdc(p_state->sam_ldb)) {
4273 return NT_STATUS_INVALID_DOMAIN_ROLE;
4276 if (samdb_rodc(p_state->sam_ldb)) {
4277 return NT_STATUS_NO_SUCH_DOMAIN;
4280 /* check caller has TRUSTED_SET_AUTH */
4282 /* fetch all trusted domain objects */
4283 num_res = gendb_search(p_state->sam_ldb, mem_ctx,
4285 &dom_res, trust_attrs,
4286 "(objectclass=trustedDomain)");
4288 return NT_STATUS_NO_SUCH_DOMAIN;
4291 for (i = 0; i < num_res; i++) {
4292 td_name = ldb_msg_find_attr_as_string(dom_res[i],
4293 "trustPartner", NULL);
4295 return NT_STATUS_INVALID_DOMAIN_STATE;
4297 if (strcasecmp_m(td_name,
4298 r->in.trusted_domain_name->string) == 0) {
4303 return NT_STATUS_NO_SUCH_DOMAIN;
4306 tdo_dn = dom_res[i]->dn;
4308 trust_attributes = samdb_result_uint(dom_res[i],
4309 "trustAttributes", 0);
4310 if (!(trust_attributes & NETR_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
4311 return NT_STATUS_INVALID_PARAMETER;
4314 if (r->in.highest_record_type >= LSA_FOREST_TRUST_RECORD_TYPE_LAST) {
4315 return NT_STATUS_INVALID_PARAMETER;
4318 nfti = talloc(mem_ctx, struct ForestTrustInfo);
4320 return NT_STATUS_NO_MEMORY;
4323 nt_status = make_ft_info(nfti, r->in.forest_trust_info, nfti);
4324 if (!NT_STATUS_IS_OK(nt_status)) {
4328 c_info = talloc_zero(r->out.collision_info,
4329 struct lsa_ForestTrustCollisionInfo);
4331 return NT_STATUS_NO_MEMORY;
4334 /* first check own info, then other domains */
4335 fti = talloc(mem_ctx, struct ForestTrustInfo);
4337 return NT_STATUS_NO_MEMORY;
4340 nt_status = own_ft_info(p_state, fti);
4341 if (!NT_STATUS_IS_OK(nt_status)) {
4345 nt_status = check_ft_info(c_info, p_state->domain_dns,
4347 if (!NT_STATUS_IS_OK(nt_status)) {
4351 for (i = 0; i < num_res; i++) {
4352 fti = talloc(mem_ctx, struct ForestTrustInfo);
4354 return NT_STATUS_NO_MEMORY;
4357 nt_status = get_ft_info(mem_ctx, ic, dom_res[i], fti);
4358 if (!NT_STATUS_IS_OK(nt_status)) {
4359 if (NT_STATUS_EQUAL(nt_status,
4360 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4366 td_name = ldb_msg_find_attr_as_string(dom_res[i],
4367 "trustPartner", NULL);
4369 return NT_STATUS_INVALID_DOMAIN_STATE;
4372 nt_status = check_ft_info(c_info, td_name, fti, nfti, c_info);
4373 if (!NT_STATUS_IS_OK(nt_status)) {
4378 *r->out.collision_info = c_info;
4380 if (r->in.check_only != 0) {
4381 return NT_STATUS_OK;
4384 /* not just a check, write info back */
4386 ndr_err = ndr_push_struct_blob(&ft_blob, mem_ctx, ic,
4388 (ndr_push_flags_fn_t)ndr_push_ForestTrustInfo);
4389 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
4390 return NT_STATUS_INVALID_PARAMETER;
4393 msg = ldb_msg_new(mem_ctx);
4395 return NT_STATUS_NO_MEMORY;
4398 msg->dn = ldb_dn_copy(mem_ctx, tdo_dn);
4400 return NT_STATUS_NO_MEMORY;
4403 ret = ldb_msg_add_empty(msg, "msDS-TrustForestTrustInfo",
4404 LDB_FLAG_MOD_REPLACE, NULL);
4405 if (ret != LDB_SUCCESS) {
4406 return NT_STATUS_NO_MEMORY;
4408 ret = ldb_msg_add_value(msg, "msDS-TrustForestTrustInfo",
4410 if (ret != LDB_SUCCESS) {
4411 return NT_STATUS_NO_MEMORY;
4414 ret = ldb_modify(p_state->sam_ldb, msg);
4415 if (ret != LDB_SUCCESS) {
4416 DEBUG(0, ("Failed to store Forest Trust Info: %s\n",
4417 ldb_errstring(p_state->sam_ldb)));
4420 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
4421 return NT_STATUS_ACCESS_DENIED;
4423 return NT_STATUS_INTERNAL_DB_CORRUPTION;
4427 return NT_STATUS_OK;
4433 static NTSTATUS dcesrv_lsa_CREDRRENAME(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4434 struct lsa_CREDRRENAME *r)
4436 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4442 lsa_LSAROPENPOLICYSCE
4444 static NTSTATUS dcesrv_lsa_LSAROPENPOLICYSCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4445 struct lsa_LSAROPENPOLICYSCE *r)
4447 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4452 lsa_LSARADTREGISTERSECURITYEVENTSOURCE
4454 static NTSTATUS dcesrv_lsa_LSARADTREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4455 struct lsa_LSARADTREGISTERSECURITYEVENTSOURCE *r)
4457 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4462 lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE
4464 static NTSTATUS dcesrv_lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4465 struct lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE *r)
4467 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4472 lsa_LSARADTREPORTSECURITYEVENT
4474 static NTSTATUS dcesrv_lsa_LSARADTREPORTSECURITYEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4475 struct lsa_LSARADTREPORTSECURITYEVENT *r)
4477 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4481 /* include the generated boilerplate */
4482 #include "librpc/gen_ndr/ndr_lsa_s.c"
4486 /*****************************************
4487 NOTE! The remaining calls below were
4488 removed in w2k3, so the DCESRV_FAULT()
4489 replies are the correct implementation. Do
4490 not try and fill these in with anything else
4491 ******************************************/
4494 dssetup_DsRoleDnsNameToFlatName
4496 static WERROR dcesrv_dssetup_DsRoleDnsNameToFlatName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4497 struct dssetup_DsRoleDnsNameToFlatName *r)
4499 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4504 dssetup_DsRoleDcAsDc
4506 static WERROR dcesrv_dssetup_DsRoleDcAsDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4507 struct dssetup_DsRoleDcAsDc *r)
4509 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4514 dssetup_DsRoleDcAsReplica
4516 static WERROR dcesrv_dssetup_DsRoleDcAsReplica(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4517 struct dssetup_DsRoleDcAsReplica *r)
4519 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4524 dssetup_DsRoleDemoteDc
4526 static WERROR dcesrv_dssetup_DsRoleDemoteDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4527 struct dssetup_DsRoleDemoteDc *r)
4529 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4534 dssetup_DsRoleGetDcOperationProgress
4536 static WERROR dcesrv_dssetup_DsRoleGetDcOperationProgress(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4537 struct dssetup_DsRoleGetDcOperationProgress *r)
4539 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4544 dssetup_DsRoleGetDcOperationResults
4546 static WERROR dcesrv_dssetup_DsRoleGetDcOperationResults(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4547 struct dssetup_DsRoleGetDcOperationResults *r)
4549 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4554 dssetup_DsRoleCancel
4556 static WERROR dcesrv_dssetup_DsRoleCancel(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4557 struct dssetup_DsRoleCancel *r)
4559 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4564 dssetup_DsRoleServerSaveStateForUpgrade
4566 static WERROR dcesrv_dssetup_DsRoleServerSaveStateForUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4567 struct dssetup_DsRoleServerSaveStateForUpgrade *r)
4569 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4574 dssetup_DsRoleUpgradeDownlevelServer
4576 static WERROR dcesrv_dssetup_DsRoleUpgradeDownlevelServer(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4577 struct dssetup_DsRoleUpgradeDownlevelServer *r)
4579 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4584 dssetup_DsRoleAbortDownlevelServerUpgrade
4586 static WERROR dcesrv_dssetup_DsRoleAbortDownlevelServerUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4587 struct dssetup_DsRoleAbortDownlevelServerUpgrade *r)
4589 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4593 /* include the generated boilerplate */
4594 #include "librpc/gen_ndr/ndr_dssetup_s.c"
4596 NTSTATUS dcerpc_server_lsa_init(void)
4600 ret = dcerpc_server_dssetup_init();
4601 if (!NT_STATUS_IS_OK(ret)) {
4604 ret = dcerpc_server_lsarpc_init();
4605 if (!NT_STATUS_IS_OK(ret)) {