lsa4: Remove an unused variable
[Samba.git] / source4 / rpc_server / lsa / dcesrv_lsa.c
blob8d1a8565f1fd0a0a8c6285aa92dd08c2f5b68188
1 /* need access mask/acl implementation */
3 /*
4 Unix SMB/CIFS implementation.
6 endpoint server for the lsarpc pipe
8 Copyright (C) Andrew Tridgell 2004
9 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2008
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 3 of the License, or
14 (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program. If not, see <http://www.gnu.org/licenses/>.
25 #include "rpc_server/lsa/lsa.h"
26 #include "system/kerberos.h"
27 #include "auth/kerberos/kerberos.h"
28 #include "librpc/gen_ndr/ndr_drsblobs.h"
29 #include "librpc/gen_ndr/ndr_lsa.h"
30 #include "../lib/crypto/crypto.h"
31 #include "lib/util/tsort.h"
32 #include "dsdb/common/util.h"
33 #include "libcli/security/session.h"
34 #include "libcli/lsarpc/util_lsarpc.h"
37 this type allows us to distinguish handle types
41 state associated with a lsa_OpenAccount() operation
43 struct lsa_account_state {
44 struct lsa_policy_state *policy;
45 uint32_t access_mask;
46 struct dom_sid *account_sid;
51 state associated with a lsa_OpenSecret() operation
53 struct lsa_secret_state {
54 struct lsa_policy_state *policy;
55 uint32_t access_mask;
56 struct ldb_dn *secret_dn;
57 struct ldb_context *sam_ldb;
58 bool global;
62 state associated with a lsa_OpenTrustedDomain() operation
64 struct lsa_trusted_domain_state {
65 struct lsa_policy_state *policy;
66 uint32_t access_mask;
67 struct ldb_dn *trusted_domain_dn;
68 struct ldb_dn *trusted_domain_user_dn;
72 this is based on the samba3 function make_lsa_object_sd()
73 It uses the same logic, but with samba4 helper functions
75 static NTSTATUS dcesrv_build_lsa_sd(TALLOC_CTX *mem_ctx,
76 struct security_descriptor **sd,
77 struct dom_sid *sid,
78 uint32_t sid_access)
80 NTSTATUS status;
81 uint32_t rid;
82 struct dom_sid *domain_sid, *domain_admins_sid;
83 const char *domain_admins_sid_str, *sidstr;
84 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
86 status = dom_sid_split_rid(tmp_ctx, sid, &domain_sid, &rid);
87 NT_STATUS_NOT_OK_RETURN_AND_FREE(status, tmp_ctx);
89 domain_admins_sid = dom_sid_add_rid(tmp_ctx, domain_sid, DOMAIN_RID_ADMINS);
90 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(domain_admins_sid, tmp_ctx);
92 domain_admins_sid_str = dom_sid_string(tmp_ctx, domain_admins_sid);
93 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(domain_admins_sid_str, tmp_ctx);
95 sidstr = dom_sid_string(tmp_ctx, sid);
96 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sidstr, tmp_ctx);
98 *sd = security_descriptor_dacl_create(mem_ctx,
99 0, sidstr, NULL,
101 SID_WORLD,
102 SEC_ACE_TYPE_ACCESS_ALLOWED,
103 SEC_GENERIC_EXECUTE | SEC_GENERIC_READ, 0,
105 SID_BUILTIN_ADMINISTRATORS,
106 SEC_ACE_TYPE_ACCESS_ALLOWED,
107 SEC_GENERIC_ALL, 0,
109 SID_BUILTIN_ACCOUNT_OPERATORS,
110 SEC_ACE_TYPE_ACCESS_ALLOWED,
111 SEC_GENERIC_ALL, 0,
113 domain_admins_sid_str,
114 SEC_ACE_TYPE_ACCESS_ALLOWED,
115 SEC_GENERIC_ALL, 0,
117 sidstr,
118 SEC_ACE_TYPE_ACCESS_ALLOWED,
119 sid_access, 0,
121 NULL);
122 talloc_free(tmp_ctx);
124 NT_STATUS_HAVE_NO_MEMORY(*sd);
126 return NT_STATUS_OK;
130 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call,
131 TALLOC_CTX *mem_ctx,
132 struct lsa_EnumAccountRights *r);
134 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
135 TALLOC_CTX *mem_ctx,
136 struct lsa_policy_state *state,
137 int ldb_flag,
138 struct dom_sid *sid,
139 const struct lsa_RightSet *rights);
142 lsa_Close
144 static NTSTATUS dcesrv_lsa_Close(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
145 struct lsa_Close *r)
147 enum dcerpc_transport_t transport = dce_call->conn->endpoint->ep_description->transport;
148 struct dcesrv_handle *h;
150 if (transport != NCACN_NP && transport != NCALRPC) {
151 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
154 *r->out.handle = *r->in.handle;
156 DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
158 talloc_free(h);
160 ZERO_STRUCTP(r->out.handle);
162 return NT_STATUS_OK;
167 lsa_Delete
169 static NTSTATUS dcesrv_lsa_Delete(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
170 struct lsa_Delete *r)
172 return NT_STATUS_NOT_SUPPORTED;
177 lsa_DeleteObject
179 static NTSTATUS dcesrv_lsa_DeleteObject(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
180 struct lsa_DeleteObject *r)
182 struct dcesrv_handle *h;
183 int ret;
185 DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
187 if (h->wire_handle.handle_type == LSA_HANDLE_SECRET) {
188 struct lsa_secret_state *secret_state = h->data;
190 /* Ensure user is permitted to delete this... */
191 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
193 case SECURITY_SYSTEM:
194 case SECURITY_ADMINISTRATOR:
195 break;
196 default:
197 /* Users and anonymous are not allowed to delete things */
198 return NT_STATUS_ACCESS_DENIED;
201 ret = ldb_delete(secret_state->sam_ldb,
202 secret_state->secret_dn);
203 if (ret != LDB_SUCCESS) {
204 return NT_STATUS_INVALID_HANDLE;
207 ZERO_STRUCTP(r->out.handle);
209 return NT_STATUS_OK;
211 } else if (h->wire_handle.handle_type == LSA_HANDLE_TRUSTED_DOMAIN) {
212 struct lsa_trusted_domain_state *trusted_domain_state =
213 talloc_get_type(h->data, struct lsa_trusted_domain_state);
214 ret = ldb_transaction_start(trusted_domain_state->policy->sam_ldb);
215 if (ret != LDB_SUCCESS) {
216 return NT_STATUS_INTERNAL_DB_CORRUPTION;
219 ret = ldb_delete(trusted_domain_state->policy->sam_ldb,
220 trusted_domain_state->trusted_domain_dn);
221 if (ret != LDB_SUCCESS) {
222 ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
223 return NT_STATUS_INVALID_HANDLE;
226 if (trusted_domain_state->trusted_domain_user_dn) {
227 ret = ldb_delete(trusted_domain_state->policy->sam_ldb,
228 trusted_domain_state->trusted_domain_user_dn);
229 if (ret != LDB_SUCCESS) {
230 ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
231 return NT_STATUS_INVALID_HANDLE;
235 ret = ldb_transaction_commit(trusted_domain_state->policy->sam_ldb);
236 if (ret != LDB_SUCCESS) {
237 return NT_STATUS_INTERNAL_DB_CORRUPTION;
240 ZERO_STRUCTP(r->out.handle);
242 return NT_STATUS_OK;
244 } else if (h->wire_handle.handle_type == LSA_HANDLE_ACCOUNT) {
245 struct lsa_RightSet *rights;
246 struct lsa_account_state *astate;
247 struct lsa_EnumAccountRights r2;
248 NTSTATUS status;
250 rights = talloc(mem_ctx, struct lsa_RightSet);
252 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
254 astate = h->data;
256 r2.in.handle = &astate->policy->handle->wire_handle;
257 r2.in.sid = astate->account_sid;
258 r2.out.rights = rights;
260 /* dcesrv_lsa_EnumAccountRights takes a LSA_HANDLE_POLICY,
261 but we have a LSA_HANDLE_ACCOUNT here, so this call
262 will always fail */
263 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
264 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
265 return NT_STATUS_OK;
268 if (!NT_STATUS_IS_OK(status)) {
269 return status;
272 status = dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
273 LDB_FLAG_MOD_DELETE, astate->account_sid,
274 r2.out.rights);
275 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
276 return NT_STATUS_OK;
279 if (!NT_STATUS_IS_OK(status)) {
280 return status;
283 ZERO_STRUCTP(r->out.handle);
285 return NT_STATUS_OK;
288 return NT_STATUS_INVALID_HANDLE;
293 lsa_EnumPrivs
295 static NTSTATUS dcesrv_lsa_EnumPrivs(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
296 struct lsa_EnumPrivs *r)
298 struct dcesrv_handle *h;
299 uint32_t i;
300 enum sec_privilege priv;
301 const char *privname;
303 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
305 i = *r->in.resume_handle;
307 while (((priv = sec_privilege_from_index(i)) != SEC_PRIV_INVALID) &&
308 r->out.privs->count < r->in.max_count) {
309 struct lsa_PrivEntry *e;
310 privname = sec_privilege_name(priv);
311 r->out.privs->privs = talloc_realloc(r->out.privs,
312 r->out.privs->privs,
313 struct lsa_PrivEntry,
314 r->out.privs->count+1);
315 if (r->out.privs->privs == NULL) {
316 return NT_STATUS_NO_MEMORY;
318 e = &r->out.privs->privs[r->out.privs->count];
319 e->luid.low = priv;
320 e->luid.high = 0;
321 e->name.string = privname;
322 r->out.privs->count++;
323 i++;
326 *r->out.resume_handle = i;
328 return NT_STATUS_OK;
333 lsa_QuerySecObj
335 static NTSTATUS dcesrv_lsa_QuerySecurity(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
336 struct lsa_QuerySecurity *r)
338 struct dcesrv_handle *h;
339 struct security_descriptor *sd;
340 NTSTATUS status;
341 struct dom_sid *sid;
343 DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
345 sid = &dce_call->conn->auth_state.session_info->security_token->sids[PRIMARY_USER_SID_INDEX];
347 if (h->wire_handle.handle_type == LSA_HANDLE_POLICY) {
348 status = dcesrv_build_lsa_sd(mem_ctx, &sd, sid, 0);
349 } else if (h->wire_handle.handle_type == LSA_HANDLE_ACCOUNT) {
350 status = dcesrv_build_lsa_sd(mem_ctx, &sd, sid,
351 LSA_ACCOUNT_ALL_ACCESS);
352 } else {
353 return NT_STATUS_INVALID_HANDLE;
355 NT_STATUS_NOT_OK_RETURN(status);
357 (*r->out.sdbuf) = talloc(mem_ctx, struct sec_desc_buf);
358 NT_STATUS_HAVE_NO_MEMORY(*r->out.sdbuf);
360 (*r->out.sdbuf)->sd = sd;
362 return NT_STATUS_OK;
367 lsa_SetSecObj
369 static NTSTATUS dcesrv_lsa_SetSecObj(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
370 struct lsa_SetSecObj *r)
372 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
377 lsa_ChangePassword
379 static NTSTATUS dcesrv_lsa_ChangePassword(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
380 struct lsa_ChangePassword *r)
382 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
386 dssetup_DsRoleGetPrimaryDomainInformation
388 This is not an LSA call, but is the only call left on the DSSETUP
389 pipe (after the pipe was truncated), and needs lsa_get_policy_state
391 static WERROR dcesrv_dssetup_DsRoleGetPrimaryDomainInformation(struct dcesrv_call_state *dce_call,
392 TALLOC_CTX *mem_ctx,
393 struct dssetup_DsRoleGetPrimaryDomainInformation *r)
395 union dssetup_DsRoleInfo *info;
397 info = talloc_zero(mem_ctx, union dssetup_DsRoleInfo);
398 W_ERROR_HAVE_NO_MEMORY(info);
400 switch (r->in.level) {
401 case DS_ROLE_BASIC_INFORMATION:
403 enum dssetup_DsRole role = DS_ROLE_STANDALONE_SERVER;
404 uint32_t flags = 0;
405 const char *domain = NULL;
406 const char *dns_domain = NULL;
407 const char *forest = NULL;
408 struct GUID domain_guid;
409 struct lsa_policy_state *state;
411 NTSTATUS status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx, &state);
412 if (!NT_STATUS_IS_OK(status)) {
413 return ntstatus_to_werror(status);
416 ZERO_STRUCT(domain_guid);
418 switch (lpcfg_server_role(dce_call->conn->dce_ctx->lp_ctx)) {
419 case ROLE_STANDALONE:
420 role = DS_ROLE_STANDALONE_SERVER;
421 break;
422 case ROLE_DOMAIN_MEMBER:
423 role = DS_ROLE_MEMBER_SERVER;
424 break;
425 case ROLE_ACTIVE_DIRECTORY_DC:
426 if (samdb_is_pdc(state->sam_ldb)) {
427 role = DS_ROLE_PRIMARY_DC;
428 } else {
429 role = DS_ROLE_BACKUP_DC;
431 break;
434 switch (lpcfg_server_role(dce_call->conn->dce_ctx->lp_ctx)) {
435 case ROLE_STANDALONE:
436 domain = talloc_strdup(mem_ctx, lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx));
437 W_ERROR_HAVE_NO_MEMORY(domain);
438 break;
439 case ROLE_DOMAIN_MEMBER:
440 domain = talloc_strdup(mem_ctx, lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx));
441 W_ERROR_HAVE_NO_MEMORY(domain);
442 /* TODO: what is with dns_domain and forest and guid? */
443 break;
444 case ROLE_ACTIVE_DIRECTORY_DC:
445 flags = DS_ROLE_PRIMARY_DS_RUNNING;
447 if (state->mixed_domain == 1) {
448 flags |= DS_ROLE_PRIMARY_DS_MIXED_MODE;
451 domain = state->domain_name;
452 dns_domain = state->domain_dns;
453 forest = state->forest_dns;
455 domain_guid = state->domain_guid;
456 flags |= DS_ROLE_PRIMARY_DOMAIN_GUID_PRESENT;
457 break;
460 info->basic.role = role;
461 info->basic.flags = flags;
462 info->basic.domain = domain;
463 info->basic.dns_domain = dns_domain;
464 info->basic.forest = forest;
465 info->basic.domain_guid = domain_guid;
467 r->out.info = info;
468 return WERR_OK;
470 case DS_ROLE_UPGRADE_STATUS:
472 info->upgrade.upgrading = DS_ROLE_NOT_UPGRADING;
473 info->upgrade.previous_role = DS_ROLE_PREVIOUS_UNKNOWN;
475 r->out.info = info;
476 return WERR_OK;
478 case DS_ROLE_OP_STATUS:
480 info->opstatus.status = DS_ROLE_OP_IDLE;
482 r->out.info = info;
483 return WERR_OK;
485 default:
486 return WERR_INVALID_PARAM;
491 fill in the AccountDomain info
493 static NTSTATUS dcesrv_lsa_info_AccountDomain(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
494 struct lsa_DomainInfo *info)
496 info->name.string = state->domain_name;
497 info->sid = state->domain_sid;
499 return NT_STATUS_OK;
503 fill in the DNS domain info
505 static NTSTATUS dcesrv_lsa_info_DNS(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
506 struct lsa_DnsDomainInfo *info)
508 info->name.string = state->domain_name;
509 info->sid = state->domain_sid;
510 info->dns_domain.string = state->domain_dns;
511 info->dns_forest.string = state->forest_dns;
512 info->domain_guid = state->domain_guid;
514 return NT_STATUS_OK;
518 lsa_QueryInfoPolicy2
520 static NTSTATUS dcesrv_lsa_QueryInfoPolicy2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
521 struct lsa_QueryInfoPolicy2 *r)
523 struct lsa_policy_state *state;
524 struct dcesrv_handle *h;
525 union lsa_PolicyInformation *info;
527 *r->out.info = NULL;
529 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
531 state = h->data;
533 info = talloc_zero(mem_ctx, union lsa_PolicyInformation);
534 if (!info) {
535 return NT_STATUS_NO_MEMORY;
537 *r->out.info = info;
539 switch (r->in.level) {
540 case LSA_POLICY_INFO_AUDIT_LOG:
541 /* we don't need to fill in any of this */
542 ZERO_STRUCT(info->audit_log);
543 return NT_STATUS_OK;
544 case LSA_POLICY_INFO_AUDIT_EVENTS:
545 /* we don't need to fill in any of this */
546 ZERO_STRUCT(info->audit_events);
547 return NT_STATUS_OK;
548 case LSA_POLICY_INFO_PD:
549 /* we don't need to fill in any of this */
550 ZERO_STRUCT(info->pd);
551 return NT_STATUS_OK;
553 case LSA_POLICY_INFO_DOMAIN:
554 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->domain);
555 case LSA_POLICY_INFO_ACCOUNT_DOMAIN:
556 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->account_domain);
557 case LSA_POLICY_INFO_L_ACCOUNT_DOMAIN:
558 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->l_account_domain);
560 case LSA_POLICY_INFO_ROLE:
561 info->role.role = LSA_ROLE_PRIMARY;
562 return NT_STATUS_OK;
564 case LSA_POLICY_INFO_DNS:
565 case LSA_POLICY_INFO_DNS_INT:
566 return dcesrv_lsa_info_DNS(state, mem_ctx, &info->dns);
568 case LSA_POLICY_INFO_REPLICA:
569 ZERO_STRUCT(info->replica);
570 return NT_STATUS_OK;
572 case LSA_POLICY_INFO_QUOTA:
573 ZERO_STRUCT(info->quota);
574 return NT_STATUS_OK;
576 case LSA_POLICY_INFO_MOD:
577 case LSA_POLICY_INFO_AUDIT_FULL_SET:
578 case LSA_POLICY_INFO_AUDIT_FULL_QUERY:
579 /* windows gives INVALID_PARAMETER */
580 *r->out.info = NULL;
581 return NT_STATUS_INVALID_PARAMETER;
584 *r->out.info = NULL;
585 return NT_STATUS_INVALID_INFO_CLASS;
589 lsa_QueryInfoPolicy
591 static NTSTATUS dcesrv_lsa_QueryInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
592 struct lsa_QueryInfoPolicy *r)
594 struct lsa_QueryInfoPolicy2 r2;
595 NTSTATUS status;
597 ZERO_STRUCT(r2);
599 r2.in.handle = r->in.handle;
600 r2.in.level = r->in.level;
601 r2.out.info = r->out.info;
603 status = dcesrv_lsa_QueryInfoPolicy2(dce_call, mem_ctx, &r2);
605 return status;
609 lsa_SetInfoPolicy
611 static NTSTATUS dcesrv_lsa_SetInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
612 struct lsa_SetInfoPolicy *r)
614 /* need to support this */
615 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
620 lsa_ClearAuditLog
622 static NTSTATUS dcesrv_lsa_ClearAuditLog(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
623 struct lsa_ClearAuditLog *r)
625 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
630 lsa_CreateAccount
632 This call does not seem to have any long-term effects, hence no database operations
634 we need to talk to the MS product group to find out what this account database means!
636 answer is that the lsa database is totally separate from the SAM and
637 ldap databases. We are going to need a separate ldb to store these
638 accounts. The SIDs on this account bear no relation to the SIDs in
641 static NTSTATUS dcesrv_lsa_CreateAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
642 struct lsa_CreateAccount *r)
644 struct lsa_account_state *astate;
646 struct lsa_policy_state *state;
647 struct dcesrv_handle *h, *ah;
649 ZERO_STRUCTP(r->out.acct_handle);
651 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
653 state = h->data;
655 astate = talloc(dce_call->conn, struct lsa_account_state);
656 if (astate == NULL) {
657 return NT_STATUS_NO_MEMORY;
660 astate->account_sid = dom_sid_dup(astate, r->in.sid);
661 if (astate->account_sid == NULL) {
662 talloc_free(astate);
663 return NT_STATUS_NO_MEMORY;
666 astate->policy = talloc_reference(astate, state);
667 astate->access_mask = r->in.access_mask;
669 ah = dcesrv_handle_new(dce_call->context, LSA_HANDLE_ACCOUNT);
670 if (!ah) {
671 talloc_free(astate);
672 return NT_STATUS_NO_MEMORY;
675 ah->data = talloc_steal(ah, astate);
677 *r->out.acct_handle = ah->wire_handle;
679 return NT_STATUS_OK;
684 lsa_EnumAccounts
686 static NTSTATUS dcesrv_lsa_EnumAccounts(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
687 struct lsa_EnumAccounts *r)
689 struct dcesrv_handle *h;
690 struct lsa_policy_state *state;
691 int ret;
692 struct ldb_message **res;
693 const char * const attrs[] = { "objectSid", NULL};
694 uint32_t count, i;
696 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
698 state = h->data;
700 /* NOTE: This call must only return accounts that have at least
701 one privilege set
703 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
704 "(&(objectSid=*)(privilege=*))");
705 if (ret < 0) {
706 return NT_STATUS_INTERNAL_DB_CORRUPTION;
709 if (*r->in.resume_handle >= ret) {
710 return NT_STATUS_NO_MORE_ENTRIES;
713 count = ret - *r->in.resume_handle;
714 if (count > r->in.num_entries) {
715 count = r->in.num_entries;
718 if (count == 0) {
719 return NT_STATUS_NO_MORE_ENTRIES;
722 r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, count);
723 if (r->out.sids->sids == NULL) {
724 return NT_STATUS_NO_MEMORY;
727 for (i=0;i<count;i++) {
728 r->out.sids->sids[i].sid =
729 samdb_result_dom_sid(r->out.sids->sids,
730 res[i + *r->in.resume_handle],
731 "objectSid");
732 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
735 r->out.sids->num_sids = count;
736 *r->out.resume_handle = count + *r->in.resume_handle;
738 return NT_STATUS_OK;
741 /* This decrypts and returns Trusted Domain Auth Information Internal data */
742 static NTSTATUS get_trustdom_auth_blob(struct dcesrv_call_state *dce_call,
743 TALLOC_CTX *mem_ctx, DATA_BLOB *auth_blob,
744 struct trustDomainPasswords *auth_struct)
746 DATA_BLOB session_key = data_blob(NULL, 0);
747 enum ndr_err_code ndr_err;
748 NTSTATUS nt_status;
750 nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
751 if (!NT_STATUS_IS_OK(nt_status)) {
752 return nt_status;
755 arcfour_crypt_blob(auth_blob->data, auth_blob->length, &session_key);
756 ndr_err = ndr_pull_struct_blob(auth_blob, mem_ctx,
757 auth_struct,
758 (ndr_pull_flags_fn_t)ndr_pull_trustDomainPasswords);
759 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
760 return NT_STATUS_INVALID_PARAMETER;
763 return NT_STATUS_OK;
766 static NTSTATUS get_trustauth_inout_blob(struct dcesrv_call_state *dce_call,
767 TALLOC_CTX *mem_ctx,
768 struct trustAuthInOutBlob *iopw,
769 DATA_BLOB *trustauth_blob)
771 enum ndr_err_code ndr_err;
773 ndr_err = ndr_push_struct_blob(trustauth_blob, mem_ctx,
774 iopw,
775 (ndr_push_flags_fn_t)ndr_push_trustAuthInOutBlob);
776 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
777 return NT_STATUS_INVALID_PARAMETER;
780 return NT_STATUS_OK;
783 static NTSTATUS add_trust_user(TALLOC_CTX *mem_ctx,
784 struct ldb_context *sam_ldb,
785 struct ldb_dn *base_dn,
786 const char *netbios_name,
787 struct trustAuthInOutBlob *in,
788 struct ldb_dn **user_dn)
790 struct ldb_message *msg;
791 struct ldb_dn *dn;
792 uint32_t i;
793 int ret;
795 dn = ldb_dn_copy(mem_ctx, base_dn);
796 if (!dn) {
797 return NT_STATUS_NO_MEMORY;
799 if (!ldb_dn_add_child_fmt(dn, "cn=%s$,cn=users", netbios_name)) {
800 return NT_STATUS_NO_MEMORY;
803 msg = ldb_msg_new(mem_ctx);
804 if (!msg) {
805 return NT_STATUS_NO_MEMORY;
807 msg->dn = dn;
809 ret = ldb_msg_add_string(msg, "objectClass", "user");
810 if (ret != LDB_SUCCESS) {
811 return NT_STATUS_NO_MEMORY;
814 ret = ldb_msg_add_fmt(msg, "samAccountName", "%s$", netbios_name);
815 if (ret != LDB_SUCCESS) {
816 return NT_STATUS_NO_MEMORY;
819 ret = samdb_msg_add_uint(sam_ldb, msg, msg, "userAccountControl",
820 UF_INTERDOMAIN_TRUST_ACCOUNT);
821 if (ret != LDB_SUCCESS) {
822 return NT_STATUS_NO_MEMORY;
825 for (i = 0; i < in->count; i++) {
826 const char *attribute;
827 struct ldb_val v;
828 switch (in->current.array[i].AuthType) {
829 case TRUST_AUTH_TYPE_NT4OWF:
830 attribute = "unicodePwd";
831 v.data = (uint8_t *)&in->current.array[i].AuthInfo.nt4owf.password;
832 v.length = 16;
833 break;
834 case TRUST_AUTH_TYPE_CLEAR:
835 attribute = "clearTextPassword";
836 v.data = in->current.array[i].AuthInfo.clear.password;
837 v.length = in->current.array[i].AuthInfo.clear.size;
838 break;
839 default:
840 continue;
843 ret = ldb_msg_add_value(msg, attribute, &v, NULL);
844 if (ret != LDB_SUCCESS) {
845 return NT_STATUS_NO_MEMORY;
849 /* create the trusted_domain user account */
850 ret = ldb_add(sam_ldb, msg);
851 if (ret != LDB_SUCCESS) {
852 DEBUG(0,("Failed to create user record %s: %s\n",
853 ldb_dn_get_linearized(msg->dn),
854 ldb_errstring(sam_ldb)));
856 switch (ret) {
857 case LDB_ERR_ENTRY_ALREADY_EXISTS:
858 return NT_STATUS_DOMAIN_EXISTS;
859 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
860 return NT_STATUS_ACCESS_DENIED;
861 default:
862 return NT_STATUS_INTERNAL_DB_CORRUPTION;
866 if (user_dn) {
867 *user_dn = dn;
869 return NT_STATUS_OK;
873 lsa_CreateTrustedDomainEx2
875 static NTSTATUS dcesrv_lsa_CreateTrustedDomain_base(struct dcesrv_call_state *dce_call,
876 TALLOC_CTX *mem_ctx,
877 struct lsa_CreateTrustedDomainEx2 *r,
878 int op,
879 struct lsa_TrustDomainInfoAuthInfo *unencrypted_auth_info)
881 struct dcesrv_handle *policy_handle;
882 struct lsa_policy_state *policy_state;
883 struct lsa_trusted_domain_state *trusted_domain_state;
884 struct dcesrv_handle *handle;
885 struct ldb_message **msgs, *msg;
886 const char *attrs[] = {
887 NULL
889 const char *netbios_name;
890 const char *dns_name;
891 const char *name;
892 DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
893 struct trustDomainPasswords auth_struct;
894 int ret;
895 NTSTATUS nt_status;
896 struct ldb_context *sam_ldb;
898 DCESRV_PULL_HANDLE(policy_handle, r->in.policy_handle, LSA_HANDLE_POLICY);
899 ZERO_STRUCTP(r->out.trustdom_handle);
901 policy_state = policy_handle->data;
902 sam_ldb = policy_state->sam_ldb;
904 netbios_name = r->in.info->netbios_name.string;
905 if (!netbios_name) {
906 return NT_STATUS_INVALID_PARAMETER;
909 dns_name = r->in.info->domain_name.string;
911 trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
912 if (!trusted_domain_state) {
913 return NT_STATUS_NO_MEMORY;
915 trusted_domain_state->policy = policy_state;
917 if (strcasecmp(netbios_name, "BUILTIN") == 0
918 || (dns_name && strcasecmp(dns_name, "BUILTIN") == 0)
919 || (dom_sid_in_domain(policy_state->builtin_sid, r->in.info->sid))) {
920 return NT_STATUS_INVALID_PARAMETER;
923 if (strcasecmp(netbios_name, policy_state->domain_name) == 0
924 || strcasecmp(netbios_name, policy_state->domain_dns) == 0
925 || (dns_name && strcasecmp(dns_name, policy_state->domain_dns) == 0)
926 || (dns_name && strcasecmp(dns_name, policy_state->domain_name) == 0)
927 || (dom_sid_equal(policy_state->domain_sid, r->in.info->sid))) {
928 return NT_STATUS_CURRENT_DOMAIN_NOT_ALLOWED;
931 /* While this is a REF pointer, some of the functions that wrap this don't provide this */
932 if (op == NDR_LSA_CREATETRUSTEDDOMAIN) {
933 /* No secrets are created at this time, for this function */
934 auth_struct.outgoing.count = 0;
935 auth_struct.incoming.count = 0;
936 } else if (op == NDR_LSA_CREATETRUSTEDDOMAINEX2) {
937 auth_blob = data_blob_const(r->in.auth_info_internal->auth_blob.data,
938 r->in.auth_info_internal->auth_blob.size);
939 nt_status = get_trustdom_auth_blob(dce_call, mem_ctx,
940 &auth_blob, &auth_struct);
941 if (!NT_STATUS_IS_OK(nt_status)) {
942 return nt_status;
944 } else if (op == NDR_LSA_CREATETRUSTEDDOMAINEX) {
946 if (unencrypted_auth_info->incoming_count > 1) {
947 return NT_STATUS_INVALID_PARAMETER;
950 /* more investigation required here, do not create secrets for
951 * now */
952 auth_struct.outgoing.count = 0;
953 auth_struct.incoming.count = 0;
954 } else {
955 return NT_STATUS_INVALID_PARAMETER;
958 if (auth_struct.incoming.count) {
959 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
960 &auth_struct.incoming,
961 &trustAuthIncoming);
962 if (!NT_STATUS_IS_OK(nt_status)) {
963 return nt_status;
965 } else {
966 trustAuthIncoming = data_blob(NULL, 0);
969 if (auth_struct.outgoing.count) {
970 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
971 &auth_struct.outgoing,
972 &trustAuthOutgoing);
973 if (!NT_STATUS_IS_OK(nt_status)) {
974 return nt_status;
976 } else {
977 trustAuthOutgoing = data_blob(NULL, 0);
980 ret = ldb_transaction_start(sam_ldb);
981 if (ret != LDB_SUCCESS) {
982 return NT_STATUS_INTERNAL_DB_CORRUPTION;
985 if (dns_name) {
986 char *dns_encoded = ldb_binary_encode_string(mem_ctx, dns_name);
987 char *netbios_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
988 /* search for the trusted_domain record */
989 ret = gendb_search(sam_ldb,
990 mem_ctx, policy_state->system_dn, &msgs, attrs,
991 "(&(|(flatname=%s)(cn=%s)(trustPartner=%s)(flatname=%s)(cn=%s)(trustPartner=%s))(objectclass=trustedDomain))",
992 dns_encoded, dns_encoded, dns_encoded, netbios_encoded, netbios_encoded, netbios_encoded);
993 if (ret > 0) {
994 ldb_transaction_cancel(sam_ldb);
995 return NT_STATUS_OBJECT_NAME_COLLISION;
997 } else {
998 char *netbios_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
999 /* search for the trusted_domain record */
1000 ret = gendb_search(sam_ldb,
1001 mem_ctx, policy_state->system_dn, &msgs, attrs,
1002 "(&(|(flatname=%s)(cn=%s)(trustPartner=%s))(objectclass=trustedDomain))",
1003 netbios_encoded, netbios_encoded, netbios_encoded);
1004 if (ret > 0) {
1005 ldb_transaction_cancel(sam_ldb);
1006 return NT_STATUS_OBJECT_NAME_COLLISION;
1010 if (ret < 0 ) {
1011 ldb_transaction_cancel(sam_ldb);
1012 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1015 name = dns_name ? dns_name : netbios_name;
1017 msg = ldb_msg_new(mem_ctx);
1018 if (msg == NULL) {
1019 return NT_STATUS_NO_MEMORY;
1022 msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
1023 if ( ! ldb_dn_add_child_fmt(msg->dn, "cn=%s", name)) {
1024 ldb_transaction_cancel(sam_ldb);
1025 return NT_STATUS_NO_MEMORY;
1028 ldb_msg_add_string(msg, "flatname", netbios_name);
1030 if (r->in.info->sid) {
1031 ret = samdb_msg_add_dom_sid(sam_ldb, mem_ctx, msg, "securityIdentifier", r->in.info->sid);
1032 if (ret != LDB_SUCCESS) {
1033 ldb_transaction_cancel(sam_ldb);
1034 return NT_STATUS_INVALID_PARAMETER;
1038 ldb_msg_add_string(msg, "objectClass", "trustedDomain");
1040 samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustType", r->in.info->trust_type);
1042 samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustAttributes", r->in.info->trust_attributes);
1044 samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustDirection", r->in.info->trust_direction);
1046 if (dns_name) {
1047 ldb_msg_add_string(msg, "trustPartner", dns_name);
1050 if (trustAuthIncoming.data) {
1051 ret = ldb_msg_add_value(msg, "trustAuthIncoming", &trustAuthIncoming, NULL);
1052 if (ret != LDB_SUCCESS) {
1053 ldb_transaction_cancel(sam_ldb);
1054 return NT_STATUS_NO_MEMORY;
1057 if (trustAuthOutgoing.data) {
1058 ret = ldb_msg_add_value(msg, "trustAuthOutgoing", &trustAuthOutgoing, NULL);
1059 if (ret != LDB_SUCCESS) {
1060 ldb_transaction_cancel(sam_ldb);
1061 return NT_STATUS_NO_MEMORY;
1065 trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msg->dn);
1067 /* create the trusted_domain */
1068 ret = ldb_add(sam_ldb, msg);
1069 switch (ret) {
1070 case LDB_SUCCESS:
1071 break;
1072 case LDB_ERR_ENTRY_ALREADY_EXISTS:
1073 ldb_transaction_cancel(sam_ldb);
1074 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1075 ldb_dn_get_linearized(msg->dn),
1076 ldb_errstring(sam_ldb)));
1077 return NT_STATUS_DOMAIN_EXISTS;
1078 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1079 ldb_transaction_cancel(sam_ldb);
1080 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1081 ldb_dn_get_linearized(msg->dn),
1082 ldb_errstring(sam_ldb)));
1083 return NT_STATUS_ACCESS_DENIED;
1084 default:
1085 ldb_transaction_cancel(sam_ldb);
1086 DEBUG(0,("Failed to create user record %s: %s\n",
1087 ldb_dn_get_linearized(msg->dn),
1088 ldb_errstring(sam_ldb)));
1089 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1092 if (r->in.info->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
1093 struct ldb_dn *user_dn;
1094 /* Inbound trusts must also create a cn=users object to match */
1095 nt_status = add_trust_user(mem_ctx, sam_ldb,
1096 policy_state->domain_dn,
1097 netbios_name,
1098 &auth_struct.incoming,
1099 &user_dn);
1100 if (!NT_STATUS_IS_OK(nt_status)) {
1101 ldb_transaction_cancel(sam_ldb);
1102 return nt_status;
1105 /* save the trust user dn */
1106 trusted_domain_state->trusted_domain_user_dn
1107 = talloc_steal(trusted_domain_state, user_dn);
1110 ret = ldb_transaction_commit(sam_ldb);
1111 if (ret != LDB_SUCCESS) {
1112 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1115 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1116 if (!handle) {
1117 return NT_STATUS_NO_MEMORY;
1120 handle->data = talloc_steal(handle, trusted_domain_state);
1122 trusted_domain_state->access_mask = r->in.access_mask;
1123 trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
1125 *r->out.trustdom_handle = handle->wire_handle;
1127 return NT_STATUS_OK;
1131 lsa_CreateTrustedDomainEx2
1133 static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx2(struct dcesrv_call_state *dce_call,
1134 TALLOC_CTX *mem_ctx,
1135 struct lsa_CreateTrustedDomainEx2 *r)
1137 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, r, NDR_LSA_CREATETRUSTEDDOMAINEX2, NULL);
1140 lsa_CreateTrustedDomainEx
1142 static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx(struct dcesrv_call_state *dce_call,
1143 TALLOC_CTX *mem_ctx,
1144 struct lsa_CreateTrustedDomainEx *r)
1146 struct lsa_CreateTrustedDomainEx2 r2;
1148 r2.in.policy_handle = r->in.policy_handle;
1149 r2.in.info = r->in.info;
1150 r2.out.trustdom_handle = r->out.trustdom_handle;
1151 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAINEX, r->in.auth_info);
1155 lsa_CreateTrustedDomain
1157 static NTSTATUS dcesrv_lsa_CreateTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1158 struct lsa_CreateTrustedDomain *r)
1160 struct lsa_CreateTrustedDomainEx2 r2;
1162 r2.in.policy_handle = r->in.policy_handle;
1163 r2.in.info = talloc(mem_ctx, struct lsa_TrustDomainInfoInfoEx);
1164 if (!r2.in.info) {
1165 return NT_STATUS_NO_MEMORY;
1168 r2.in.info->domain_name.string = NULL;
1169 r2.in.info->netbios_name = r->in.info->name;
1170 r2.in.info->sid = r->in.info->sid;
1171 r2.in.info->trust_direction = LSA_TRUST_DIRECTION_OUTBOUND;
1172 r2.in.info->trust_type = LSA_TRUST_TYPE_DOWNLEVEL;
1173 r2.in.info->trust_attributes = 0;
1175 r2.in.access_mask = r->in.access_mask;
1176 r2.out.trustdom_handle = r->out.trustdom_handle;
1178 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAIN, NULL);
1182 lsa_OpenTrustedDomain
1184 static NTSTATUS dcesrv_lsa_OpenTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1185 struct lsa_OpenTrustedDomain *r)
1187 struct dcesrv_handle *policy_handle;
1189 struct lsa_policy_state *policy_state;
1190 struct lsa_trusted_domain_state *trusted_domain_state;
1191 struct dcesrv_handle *handle;
1192 struct ldb_message **msgs;
1193 const char *attrs[] = {
1194 "trustDirection",
1195 "flatname",
1196 NULL
1199 const char *sid_string;
1200 int ret;
1202 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1203 ZERO_STRUCTP(r->out.trustdom_handle);
1204 policy_state = policy_handle->data;
1206 trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
1207 if (!trusted_domain_state) {
1208 return NT_STATUS_NO_MEMORY;
1210 trusted_domain_state->policy = policy_state;
1212 sid_string = dom_sid_string(mem_ctx, r->in.sid);
1213 if (!sid_string) {
1214 return NT_STATUS_NO_MEMORY;
1217 /* search for the trusted_domain record */
1218 ret = gendb_search(trusted_domain_state->policy->sam_ldb,
1219 mem_ctx, policy_state->system_dn, &msgs, attrs,
1220 "(&(securityIdentifier=%s)(objectclass=trustedDomain))",
1221 sid_string);
1222 if (ret == 0) {
1223 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1226 if (ret != 1) {
1227 DEBUG(0,("Found %d records matching DN %s\n", ret,
1228 ldb_dn_get_linearized(policy_state->system_dn)));
1229 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1232 trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msgs[0]->dn);
1234 trusted_domain_state->trusted_domain_user_dn = NULL;
1236 if (ldb_msg_find_attr_as_int(msgs[0], "trustDirection", 0) & LSA_TRUST_DIRECTION_INBOUND) {
1237 const char *flatname = ldb_binary_encode_string(mem_ctx, ldb_msg_find_attr_as_string(msgs[0], "flatname", NULL));
1238 /* search for the trusted_domain record */
1239 ret = gendb_search(trusted_domain_state->policy->sam_ldb,
1240 mem_ctx, policy_state->domain_dn, &msgs, attrs,
1241 "(&(samaccountname=%s$)(objectclass=user)(userAccountControl:1.2.840.113556.1.4.803:=%u))",
1242 flatname, UF_INTERDOMAIN_TRUST_ACCOUNT);
1243 if (ret == 1) {
1244 trusted_domain_state->trusted_domain_user_dn = talloc_steal(trusted_domain_state, msgs[0]->dn);
1247 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1248 if (!handle) {
1249 return NT_STATUS_NO_MEMORY;
1252 handle->data = talloc_steal(handle, trusted_domain_state);
1254 trusted_domain_state->access_mask = r->in.access_mask;
1255 trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
1257 *r->out.trustdom_handle = handle->wire_handle;
1259 return NT_STATUS_OK;
1264 lsa_OpenTrustedDomainByName
1266 static NTSTATUS dcesrv_lsa_OpenTrustedDomainByName(struct dcesrv_call_state *dce_call,
1267 TALLOC_CTX *mem_ctx,
1268 struct lsa_OpenTrustedDomainByName *r)
1270 struct dcesrv_handle *policy_handle;
1272 struct lsa_policy_state *policy_state;
1273 struct lsa_trusted_domain_state *trusted_domain_state;
1274 struct dcesrv_handle *handle;
1275 struct ldb_message **msgs;
1276 const char *attrs[] = {
1277 NULL
1279 char *td_name;
1280 int ret;
1282 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1283 ZERO_STRUCTP(r->out.trustdom_handle);
1284 policy_state = policy_handle->data;
1286 if (!r->in.name.string) {
1287 return NT_STATUS_INVALID_PARAMETER;
1290 trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
1291 if (!trusted_domain_state) {
1292 return NT_STATUS_NO_MEMORY;
1294 trusted_domain_state->policy = policy_state;
1296 /* search for the trusted_domain record */
1297 td_name = ldb_binary_encode_string(mem_ctx, r->in.name.string);
1298 ret = gendb_search(trusted_domain_state->policy->sam_ldb,
1299 mem_ctx, policy_state->system_dn, &msgs, attrs,
1300 "(&(|(flatname=%s)(cn=%s)(trustPartner=%s))"
1301 "(objectclass=trustedDomain))",
1302 td_name, td_name, td_name);
1303 if (ret == 0) {
1304 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1307 if (ret != 1) {
1308 DEBUG(0,("Found %d records matching DN %s\n", ret,
1309 ldb_dn_get_linearized(policy_state->system_dn)));
1310 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1313 /* TODO: perform access checks */
1315 trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msgs[0]->dn);
1317 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1318 if (!handle) {
1319 return NT_STATUS_NO_MEMORY;
1322 handle->data = talloc_steal(handle, trusted_domain_state);
1324 trusted_domain_state->access_mask = r->in.access_mask;
1325 trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
1327 *r->out.trustdom_handle = handle->wire_handle;
1329 return NT_STATUS_OK;
1335 lsa_SetTrustedDomainInfo
1337 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1338 struct lsa_SetTrustedDomainInfo *r)
1340 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1345 /* parameters 4 to 6 are optional if the dn is a dn of a TDO object,
1346 * otherwise at least one must be provided */
1347 static NTSTATUS get_tdo(struct ldb_context *sam, TALLOC_CTX *mem_ctx,
1348 struct ldb_dn *basedn, const char *dns_domain,
1349 const char *netbios, struct dom_sid2 *sid,
1350 struct ldb_message ***msgs)
1352 const char *attrs[] = { "flatname", "trustPartner",
1353 "securityIdentifier", "trustDirection",
1354 "trustType", "trustAttributes",
1355 "trustPosixOffset",
1356 "msDs-supportedEncryptionTypes", NULL };
1357 char *dns = NULL;
1358 char *nbn = NULL;
1359 char *sidstr = NULL;
1360 char *filter;
1361 int ret;
1364 if (dns_domain || netbios || sid) {
1365 filter = talloc_strdup(mem_ctx,
1366 "(&(objectclass=trustedDomain)(|");
1367 } else {
1368 filter = talloc_strdup(mem_ctx,
1369 "(objectclass=trustedDomain)");
1371 if (!filter) {
1372 return NT_STATUS_NO_MEMORY;
1375 if (dns_domain) {
1376 dns = ldb_binary_encode_string(mem_ctx, dns_domain);
1377 if (!dns) {
1378 return NT_STATUS_NO_MEMORY;
1380 filter = talloc_asprintf_append(filter,
1381 "(trustPartner=%s)", dns);
1382 if (!filter) {
1383 return NT_STATUS_NO_MEMORY;
1386 if (netbios) {
1387 nbn = ldb_binary_encode_string(mem_ctx, netbios);
1388 if (!nbn) {
1389 return NT_STATUS_NO_MEMORY;
1391 filter = talloc_asprintf_append(filter,
1392 "(flatname=%s)", nbn);
1393 if (!filter) {
1394 return NT_STATUS_NO_MEMORY;
1397 if (sid) {
1398 sidstr = dom_sid_string(mem_ctx, sid);
1399 if (!sidstr) {
1400 return NT_STATUS_INVALID_PARAMETER;
1402 filter = talloc_asprintf_append(filter,
1403 "(securityIdentifier=%s)",
1404 sidstr);
1405 if (!filter) {
1406 return NT_STATUS_NO_MEMORY;
1409 if (dns_domain || netbios || sid) {
1410 filter = talloc_asprintf_append(filter, "))");
1411 if (!filter) {
1412 return NT_STATUS_NO_MEMORY;
1416 ret = gendb_search(sam, mem_ctx, basedn, msgs, attrs, "%s", filter);
1417 if (ret == 0) {
1418 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1421 if (ret != 1) {
1422 return NT_STATUS_OBJECT_NAME_COLLISION;
1425 return NT_STATUS_OK;
1428 static NTSTATUS update_uint32_t_value(TALLOC_CTX *mem_ctx,
1429 struct ldb_context *sam_ldb,
1430 struct ldb_message *orig,
1431 struct ldb_message *dest,
1432 const char *attribute,
1433 uint32_t value,
1434 uint32_t *orig_value)
1436 const struct ldb_val *orig_val;
1437 uint32_t orig_uint = 0;
1438 unsigned int flags = 0;
1439 int ret;
1441 orig_val = ldb_msg_find_ldb_val(orig, attribute);
1442 if (!orig_val || !orig_val->data) {
1443 /* add new attribute */
1444 flags = LDB_FLAG_MOD_ADD;
1446 } else {
1447 errno = 0;
1448 orig_uint = strtoul((const char *)orig_val->data, NULL, 0);
1449 if (errno != 0 || orig_uint != value) {
1450 /* replace also if can't get value */
1451 flags = LDB_FLAG_MOD_REPLACE;
1455 if (flags == 0) {
1456 /* stored value is identical, nothing to change */
1457 goto done;
1460 ret = ldb_msg_add_empty(dest, attribute, flags, NULL);
1461 if (ret != LDB_SUCCESS) {
1462 return NT_STATUS_NO_MEMORY;
1465 ret = samdb_msg_add_uint(sam_ldb, dest, dest, attribute, value);
1466 if (ret != LDB_SUCCESS) {
1467 return NT_STATUS_NO_MEMORY;
1470 done:
1471 if (orig_value) {
1472 *orig_value = orig_uint;
1474 return NT_STATUS_OK;
1477 static NTSTATUS update_trust_user(TALLOC_CTX *mem_ctx,
1478 struct ldb_context *sam_ldb,
1479 struct ldb_dn *base_dn,
1480 bool delete_user,
1481 const char *netbios_name,
1482 struct trustAuthInOutBlob *in)
1484 const char *attrs[] = { "userAccountControl", NULL };
1485 struct ldb_message **msgs;
1486 struct ldb_message *msg;
1487 uint32_t uac;
1488 uint32_t i;
1489 int ret;
1491 ret = gendb_search(sam_ldb, mem_ctx,
1492 base_dn, &msgs, attrs,
1493 "samAccountName=%s$", netbios_name);
1494 if (ret > 1) {
1495 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1498 if (ret == 0) {
1499 if (delete_user) {
1500 return NT_STATUS_OK;
1503 /* ok no existing user, add it from scratch */
1504 return add_trust_user(mem_ctx, sam_ldb, base_dn,
1505 netbios_name, in, NULL);
1508 /* check user is what we are looking for */
1509 uac = ldb_msg_find_attr_as_uint(msgs[0],
1510 "userAccountControl", 0);
1511 if (!(uac & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
1512 return NT_STATUS_OBJECT_NAME_COLLISION;
1515 if (delete_user) {
1516 ret = ldb_delete(sam_ldb, msgs[0]->dn);
1517 switch (ret) {
1518 case LDB_SUCCESS:
1519 return NT_STATUS_OK;
1520 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1521 return NT_STATUS_ACCESS_DENIED;
1522 default:
1523 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1527 /* entry exists, just modify secret if any */
1528 if (in == NULL || in->count == 0) {
1529 return NT_STATUS_OK;
1532 msg = ldb_msg_new(mem_ctx);
1533 if (!msg) {
1534 return NT_STATUS_NO_MEMORY;
1536 msg->dn = msgs[0]->dn;
1538 for (i = 0; i < in->count; i++) {
1539 const char *attribute;
1540 struct ldb_val v;
1541 switch (in->current.array[i].AuthType) {
1542 case TRUST_AUTH_TYPE_NT4OWF:
1543 attribute = "unicodePwd";
1544 v.data = (uint8_t *)&in->current.array[i].AuthInfo.nt4owf.password;
1545 v.length = 16;
1546 break;
1547 case TRUST_AUTH_TYPE_CLEAR:
1548 attribute = "clearTextPassword";
1549 v.data = in->current.array[i].AuthInfo.clear.password;
1550 v.length = in->current.array[i].AuthInfo.clear.size;
1551 break;
1552 default:
1553 continue;
1556 ret = ldb_msg_add_empty(msg, attribute,
1557 LDB_FLAG_MOD_REPLACE, NULL);
1558 if (ret != LDB_SUCCESS) {
1559 return NT_STATUS_NO_MEMORY;
1562 ret = ldb_msg_add_value(msg, attribute, &v, NULL);
1563 if (ret != LDB_SUCCESS) {
1564 return NT_STATUS_NO_MEMORY;
1568 /* create the trusted_domain user account */
1569 ret = ldb_modify(sam_ldb, msg);
1570 if (ret != LDB_SUCCESS) {
1571 DEBUG(0,("Failed to create user record %s: %s\n",
1572 ldb_dn_get_linearized(msg->dn),
1573 ldb_errstring(sam_ldb)));
1575 switch (ret) {
1576 case LDB_ERR_ENTRY_ALREADY_EXISTS:
1577 return NT_STATUS_DOMAIN_EXISTS;
1578 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1579 return NT_STATUS_ACCESS_DENIED;
1580 default:
1581 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1585 return NT_STATUS_OK;
1589 static NTSTATUS setInfoTrustedDomain_base(struct dcesrv_call_state *dce_call,
1590 struct dcesrv_handle *p_handle,
1591 TALLOC_CTX *mem_ctx,
1592 struct ldb_message *dom_msg,
1593 enum lsa_TrustDomInfoEnum level,
1594 union lsa_TrustedDomainInfo *info)
1596 struct lsa_policy_state *p_state = p_handle->data;
1597 uint32_t *posix_offset = NULL;
1598 struct lsa_TrustDomainInfoInfoEx *info_ex = NULL;
1599 struct lsa_TrustDomainInfoAuthInfo *auth_info = NULL;
1600 struct lsa_TrustDomainInfoAuthInfoInternal *auth_info_int = NULL;
1601 uint32_t *enc_types = NULL;
1602 DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
1603 struct trustDomainPasswords auth_struct;
1604 struct trustAuthInOutBlob *current_passwords = NULL;
1605 NTSTATUS nt_status;
1606 struct ldb_message **msgs;
1607 struct ldb_message *msg;
1608 bool add_outgoing = false;
1609 bool add_incoming = false;
1610 bool del_outgoing = false;
1611 bool del_incoming = false;
1612 bool in_transaction = false;
1613 int ret;
1614 bool am_rodc;
1616 switch (level) {
1617 case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
1618 posix_offset = &info->posix_offset.posix_offset;
1619 break;
1620 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
1621 info_ex = &info->info_ex;
1622 break;
1623 case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO:
1624 auth_info = &info->auth_info;
1625 break;
1626 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
1627 posix_offset = &info->full_info.posix_offset.posix_offset;
1628 info_ex = &info->full_info.info_ex;
1629 auth_info = &info->full_info.auth_info;
1630 break;
1631 case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO_INTERNAL:
1632 auth_info_int = &info->auth_info_internal;
1633 break;
1634 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_INTERNAL:
1635 posix_offset = &info->full_info_internal.posix_offset.posix_offset;
1636 info_ex = &info->full_info_internal.info_ex;
1637 auth_info_int = &info->full_info_internal.auth_info;
1638 break;
1639 case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
1640 enc_types = &info->enc_types.enc_types;
1641 break;
1642 default:
1643 return NT_STATUS_INVALID_PARAMETER;
1646 if (auth_info) {
1647 nt_status = auth_info_2_auth_blob(mem_ctx, auth_info,
1648 &trustAuthIncoming,
1649 &trustAuthOutgoing);
1650 if (!NT_STATUS_IS_OK(nt_status)) {
1651 return nt_status;
1653 if (trustAuthIncoming.data) {
1654 /* This does the decode of some of this twice, but it is easier that way */
1655 nt_status = auth_info_2_trustauth_inout(mem_ctx,
1656 auth_info->incoming_count,
1657 auth_info->incoming_current_auth_info,
1658 NULL,
1659 &current_passwords);
1660 if (!NT_STATUS_IS_OK(nt_status)) {
1661 return nt_status;
1666 /* decode auth_info_int if set */
1667 if (auth_info_int) {
1669 /* now decrypt blob */
1670 auth_blob = data_blob_const(auth_info_int->auth_blob.data,
1671 auth_info_int->auth_blob.size);
1673 nt_status = get_trustdom_auth_blob(dce_call, mem_ctx,
1674 &auth_blob, &auth_struct);
1675 if (!NT_STATUS_IS_OK(nt_status)) {
1676 return nt_status;
1680 if (info_ex) {
1681 /* verify data matches */
1682 if (info_ex->trust_attributes &
1683 LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
1684 /* TODO: check what behavior level we have */
1685 if (strcasecmp_m(p_state->domain_dns,
1686 p_state->forest_dns) != 0) {
1687 return NT_STATUS_INVALID_DOMAIN_STATE;
1691 ret = samdb_rodc(p_state->sam_ldb, &am_rodc);
1692 if (ret == LDB_SUCCESS && am_rodc) {
1693 return NT_STATUS_NO_SUCH_DOMAIN;
1696 /* verify only one object matches the dns/netbios/sid
1697 * triplet and that this is the one we already have */
1698 nt_status = get_tdo(p_state->sam_ldb, mem_ctx,
1699 p_state->system_dn,
1700 info_ex->domain_name.string,
1701 info_ex->netbios_name.string,
1702 info_ex->sid, &msgs);
1703 if (!NT_STATUS_IS_OK(nt_status)) {
1704 return nt_status;
1706 if (ldb_dn_compare(dom_msg->dn, msgs[0]->dn) != 0) {
1707 return NT_STATUS_OBJECT_NAME_COLLISION;
1709 talloc_free(msgs);
1712 /* TODO: should we fetch previous values from the existing entry
1713 * and append them ? */
1714 if (auth_info_int && auth_struct.incoming.count) {
1715 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1716 &auth_struct.incoming,
1717 &trustAuthIncoming);
1718 if (!NT_STATUS_IS_OK(nt_status)) {
1719 return nt_status;
1722 current_passwords = &auth_struct.incoming;
1724 } else {
1725 trustAuthIncoming = data_blob(NULL, 0);
1728 if (auth_info_int && auth_struct.outgoing.count) {
1729 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1730 &auth_struct.outgoing,
1731 &trustAuthOutgoing);
1732 if (!NT_STATUS_IS_OK(nt_status)) {
1733 return nt_status;
1735 } else {
1736 trustAuthOutgoing = data_blob(NULL, 0);
1739 msg = ldb_msg_new(mem_ctx);
1740 if (msg == NULL) {
1741 return NT_STATUS_NO_MEMORY;
1743 msg->dn = dom_msg->dn;
1745 if (posix_offset) {
1746 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1747 dom_msg, msg,
1748 "trustPosixOffset",
1749 *posix_offset, NULL);
1750 if (!NT_STATUS_IS_OK(nt_status)) {
1751 return nt_status;
1755 if (info_ex) {
1756 uint32_t origattrs;
1757 uint32_t origdir;
1758 int origtype;
1760 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1761 dom_msg, msg,
1762 "trustDirection",
1763 info_ex->trust_direction,
1764 &origdir);
1765 if (!NT_STATUS_IS_OK(nt_status)) {
1766 return nt_status;
1769 if (info_ex->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
1770 add_incoming = true;
1772 if (info_ex->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND) {
1773 add_outgoing = true;
1776 if ((origdir & LSA_TRUST_DIRECTION_INBOUND) &&
1777 !(info_ex->trust_direction & LSA_TRUST_DIRECTION_INBOUND)) {
1778 del_incoming = true;
1780 if ((origdir & LSA_TRUST_DIRECTION_OUTBOUND) &&
1781 !(info_ex->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND)) {
1782 del_outgoing = true;
1785 origtype = ldb_msg_find_attr_as_int(dom_msg, "trustType", -1);
1786 if (origtype == -1 || origtype != info_ex->trust_type) {
1787 DEBUG(1, ("Attempted to change trust type! "
1788 "Operation not handled\n"));
1789 return NT_STATUS_INVALID_PARAMETER;
1792 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1793 dom_msg, msg,
1794 "trustAttributes",
1795 info_ex->trust_attributes,
1796 &origattrs);
1797 if (!NT_STATUS_IS_OK(nt_status)) {
1798 return nt_status;
1800 /* TODO: check forestFunctionality from ldb opaque */
1801 /* TODO: check what is set makes sense */
1802 /* for now refuse changes */
1803 if (origattrs == -1 ||
1804 origattrs != info_ex->trust_attributes) {
1805 DEBUG(1, ("Attempted to change trust attributes! "
1806 "Operation not handled\n"));
1807 return NT_STATUS_INVALID_PARAMETER;
1811 if (enc_types) {
1812 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1813 dom_msg, msg,
1814 "msDS-SupportedEncryptionTypes",
1815 *enc_types, NULL);
1816 if (!NT_STATUS_IS_OK(nt_status)) {
1817 return nt_status;
1821 if (add_incoming && trustAuthIncoming.data) {
1822 ret = ldb_msg_add_empty(msg, "trustAuthIncoming",
1823 LDB_FLAG_MOD_REPLACE, NULL);
1824 if (ret != LDB_SUCCESS) {
1825 return NT_STATUS_NO_MEMORY;
1827 ret = ldb_msg_add_value(msg, "trustAuthIncoming",
1828 &trustAuthIncoming, NULL);
1829 if (ret != LDB_SUCCESS) {
1830 return NT_STATUS_NO_MEMORY;
1833 if (add_outgoing && trustAuthOutgoing.data) {
1834 ret = ldb_msg_add_empty(msg, "trustAuthOutgoing",
1835 LDB_FLAG_MOD_REPLACE, NULL);
1836 if (ret != LDB_SUCCESS) {
1837 return NT_STATUS_NO_MEMORY;
1839 ret = ldb_msg_add_value(msg, "trustAuthOutgoing",
1840 &trustAuthOutgoing, NULL);
1841 if (ret != LDB_SUCCESS) {
1842 return NT_STATUS_NO_MEMORY;
1846 /* start transaction */
1847 ret = ldb_transaction_start(p_state->sam_ldb);
1848 if (ret != LDB_SUCCESS) {
1849 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1851 in_transaction = true;
1853 if (msg->num_elements) {
1854 ret = ldb_modify(p_state->sam_ldb, msg);
1855 if (ret != LDB_SUCCESS) {
1856 DEBUG(1,("Failed to modify trusted domain record %s: %s\n",
1857 ldb_dn_get_linearized(msg->dn),
1858 ldb_errstring(p_state->sam_ldb)));
1859 nt_status = dsdb_ldb_err_to_ntstatus(ret);
1860 goto done;
1864 if (add_incoming || del_incoming) {
1865 const char *netbios_name;
1867 netbios_name = ldb_msg_find_attr_as_string(dom_msg,
1868 "flatname", NULL);
1869 if (!netbios_name) {
1870 nt_status = NT_STATUS_INVALID_DOMAIN_STATE;
1871 goto done;
1874 /* We use trustAuthIncoming.data to incidate that auth_struct.incoming is valid */
1875 nt_status = update_trust_user(mem_ctx,
1876 p_state->sam_ldb,
1877 p_state->domain_dn,
1878 del_incoming,
1879 netbios_name,
1880 current_passwords);
1881 if (!NT_STATUS_IS_OK(nt_status)) {
1882 goto done;
1886 /* ok, all fine, commit transaction and return */
1887 ret = ldb_transaction_commit(p_state->sam_ldb);
1888 if (ret != LDB_SUCCESS) {
1889 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1891 in_transaction = false;
1893 nt_status = NT_STATUS_OK;
1895 done:
1896 if (in_transaction) {
1897 ldb_transaction_cancel(p_state->sam_ldb);
1899 return nt_status;
1903 lsa_SetInfomrationTrustedDomain
1905 static NTSTATUS dcesrv_lsa_SetInformationTrustedDomain(
1906 struct dcesrv_call_state *dce_call,
1907 TALLOC_CTX *mem_ctx,
1908 struct lsa_SetInformationTrustedDomain *r)
1910 struct dcesrv_handle *h;
1911 struct lsa_trusted_domain_state *td_state;
1912 struct ldb_message **msgs;
1913 NTSTATUS nt_status;
1915 DCESRV_PULL_HANDLE(h, r->in.trustdom_handle,
1916 LSA_HANDLE_TRUSTED_DOMAIN);
1918 td_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
1920 /* get the trusted domain object */
1921 nt_status = get_tdo(td_state->policy->sam_ldb, mem_ctx,
1922 td_state->trusted_domain_dn,
1923 NULL, NULL, NULL, &msgs);
1924 if (!NT_STATUS_IS_OK(nt_status)) {
1925 if (NT_STATUS_EQUAL(nt_status,
1926 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1927 return nt_status;
1929 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1932 return setInfoTrustedDomain_base(dce_call, h, mem_ctx,
1933 msgs[0], r->in.level, r->in.info);
1938 lsa_DeleteTrustedDomain
1940 static NTSTATUS dcesrv_lsa_DeleteTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1941 struct lsa_DeleteTrustedDomain *r)
1943 NTSTATUS status;
1944 struct lsa_OpenTrustedDomain opn;
1945 struct lsa_DeleteObject del;
1946 struct dcesrv_handle *h;
1948 opn.in.handle = r->in.handle;
1949 opn.in.sid = r->in.dom_sid;
1950 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1951 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
1952 if (!opn.out.trustdom_handle) {
1953 return NT_STATUS_NO_MEMORY;
1955 status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
1956 if (!NT_STATUS_IS_OK(status)) {
1957 return status;
1960 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
1961 talloc_steal(mem_ctx, h);
1963 del.in.handle = opn.out.trustdom_handle;
1964 del.out.handle = opn.out.trustdom_handle;
1965 status = dcesrv_lsa_DeleteObject(dce_call, mem_ctx, &del);
1966 if (!NT_STATUS_IS_OK(status)) {
1967 return status;
1969 return NT_STATUS_OK;
1972 static NTSTATUS fill_trust_domain_ex(TALLOC_CTX *mem_ctx,
1973 struct ldb_message *msg,
1974 struct lsa_TrustDomainInfoInfoEx *info_ex)
1976 info_ex->domain_name.string
1977 = ldb_msg_find_attr_as_string(msg, "trustPartner", NULL);
1978 info_ex->netbios_name.string
1979 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
1980 info_ex->sid
1981 = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
1982 info_ex->trust_direction
1983 = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
1984 info_ex->trust_type
1985 = ldb_msg_find_attr_as_int(msg, "trustType", 0);
1986 info_ex->trust_attributes
1987 = ldb_msg_find_attr_as_int(msg, "trustAttributes", 0);
1988 return NT_STATUS_OK;
1992 lsa_QueryTrustedDomainInfo
1994 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1995 struct lsa_QueryTrustedDomainInfo *r)
1997 union lsa_TrustedDomainInfo *info = NULL;
1998 struct dcesrv_handle *h;
1999 struct lsa_trusted_domain_state *trusted_domain_state;
2000 struct ldb_message *msg;
2001 int ret;
2002 struct ldb_message **res;
2003 const char *attrs[] = {
2004 "flatname",
2005 "trustPartner",
2006 "securityIdentifier",
2007 "trustDirection",
2008 "trustType",
2009 "trustAttributes",
2010 "msDs-supportedEncryptionTypes",
2011 NULL
2014 DCESRV_PULL_HANDLE(h, r->in.trustdom_handle, LSA_HANDLE_TRUSTED_DOMAIN);
2016 trusted_domain_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
2018 /* pull all the user attributes */
2019 ret = gendb_search_dn(trusted_domain_state->policy->sam_ldb, mem_ctx,
2020 trusted_domain_state->trusted_domain_dn, &res, attrs);
2021 if (ret != 1) {
2022 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2024 msg = res[0];
2026 info = talloc_zero(mem_ctx, union lsa_TrustedDomainInfo);
2027 if (!info) {
2028 return NT_STATUS_NO_MEMORY;
2030 *r->out.info = info;
2032 switch (r->in.level) {
2033 case LSA_TRUSTED_DOMAIN_INFO_NAME:
2034 info->name.netbios_name.string
2035 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2036 break;
2037 case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
2038 info->posix_offset.posix_offset
2039 = ldb_msg_find_attr_as_uint(msg, "posixOffset", 0);
2040 break;
2041 #if 0 /* Win2k3 doesn't implement this */
2042 case LSA_TRUSTED_DOMAIN_INFO_BASIC:
2043 r->out.info->info_basic.netbios_name.string
2044 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2045 r->out.info->info_basic.sid
2046 = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
2047 break;
2048 #endif
2049 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
2050 return fill_trust_domain_ex(mem_ctx, msg, &info->info_ex);
2052 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
2053 ZERO_STRUCT(info->full_info);
2054 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info.info_ex);
2055 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_2_INTERNAL:
2056 ZERO_STRUCT(info->full_info2_internal);
2057 info->full_info2_internal.posix_offset.posix_offset
2058 = ldb_msg_find_attr_as_uint(msg, "posixOffset", 0);
2059 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info2_internal.info.info_ex);
2061 case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
2062 info->enc_types.enc_types
2063 = ldb_msg_find_attr_as_uint(msg, "msDs-supportedEncryptionTypes", KERB_ENCTYPE_RC4_HMAC_MD5);
2064 break;
2066 case LSA_TRUSTED_DOMAIN_INFO_CONTROLLERS:
2067 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX2_INTERNAL:
2068 /* oops, we don't want to return the info after all */
2069 talloc_free(info);
2070 *r->out.info = NULL;
2071 return NT_STATUS_INVALID_PARAMETER;
2072 default:
2073 /* oops, we don't want to return the info after all */
2074 talloc_free(info);
2075 *r->out.info = NULL;
2076 return NT_STATUS_INVALID_INFO_CLASS;
2079 return NT_STATUS_OK;
2084 lsa_QueryTrustedDomainInfoBySid
2086 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoBySid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2087 struct lsa_QueryTrustedDomainInfoBySid *r)
2089 NTSTATUS status;
2090 struct lsa_OpenTrustedDomain opn;
2091 struct lsa_QueryTrustedDomainInfo query;
2092 struct dcesrv_handle *h;
2094 opn.in.handle = r->in.handle;
2095 opn.in.sid = r->in.dom_sid;
2096 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2097 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2098 if (!opn.out.trustdom_handle) {
2099 return NT_STATUS_NO_MEMORY;
2101 status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
2102 if (!NT_STATUS_IS_OK(status)) {
2103 return status;
2106 /* Ensure this handle goes away at the end of this call */
2107 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2108 talloc_steal(mem_ctx, h);
2110 query.in.trustdom_handle = opn.out.trustdom_handle;
2111 query.in.level = r->in.level;
2112 query.out.info = r->out.info;
2113 status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2114 if (!NT_STATUS_IS_OK(status)) {
2115 return status;
2118 return NT_STATUS_OK;
2122 lsa_SetTrustedDomainInfoByName
2124 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2125 TALLOC_CTX *mem_ctx,
2126 struct lsa_SetTrustedDomainInfoByName *r)
2128 struct dcesrv_handle *policy_handle;
2129 struct lsa_policy_state *policy_state;
2130 struct ldb_message **msgs;
2131 NTSTATUS nt_status;
2133 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2134 policy_state = policy_handle->data;
2136 /* get the trusted domain object */
2137 nt_status = get_tdo(policy_state->sam_ldb, mem_ctx,
2138 policy_state->domain_dn,
2139 r->in.trusted_domain->string,
2140 r->in.trusted_domain->string,
2141 NULL, &msgs);
2142 if (!NT_STATUS_IS_OK(nt_status)) {
2143 if (NT_STATUS_EQUAL(nt_status,
2144 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2145 return nt_status;
2147 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2150 return setInfoTrustedDomain_base(dce_call, policy_handle, mem_ctx,
2151 msgs[0], r->in.level, r->in.info);
2155 lsa_QueryTrustedDomainInfoByName
2157 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2158 TALLOC_CTX *mem_ctx,
2159 struct lsa_QueryTrustedDomainInfoByName *r)
2161 NTSTATUS status;
2162 struct lsa_OpenTrustedDomainByName opn;
2163 struct lsa_QueryTrustedDomainInfo query;
2164 struct dcesrv_handle *h;
2166 opn.in.handle = r->in.handle;
2167 opn.in.name = *r->in.trusted_domain;
2168 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2169 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2170 if (!opn.out.trustdom_handle) {
2171 return NT_STATUS_NO_MEMORY;
2173 status = dcesrv_lsa_OpenTrustedDomainByName(dce_call, mem_ctx, &opn);
2174 if (!NT_STATUS_IS_OK(status)) {
2175 return status;
2178 /* Ensure this handle goes away at the end of this call */
2179 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2180 talloc_steal(mem_ctx, h);
2182 query.in.trustdom_handle = opn.out.trustdom_handle;
2183 query.in.level = r->in.level;
2184 query.out.info = r->out.info;
2185 status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2186 if (!NT_STATUS_IS_OK(status)) {
2187 return status;
2190 return NT_STATUS_OK;
2194 lsa_CloseTrustedDomainEx
2196 static NTSTATUS dcesrv_lsa_CloseTrustedDomainEx(struct dcesrv_call_state *dce_call,
2197 TALLOC_CTX *mem_ctx,
2198 struct lsa_CloseTrustedDomainEx *r)
2200 /* The result of a bad hair day from an IDL programmer? Not
2201 * implmented in Win2k3. You should always just lsa_Close
2202 * anyway. */
2203 return NT_STATUS_NOT_IMPLEMENTED;
2208 comparison function for sorting lsa_DomainInformation array
2210 static int compare_DomainInfo(struct lsa_DomainInfo *e1, struct lsa_DomainInfo *e2)
2212 return strcasecmp_m(e1->name.string, e2->name.string);
2216 lsa_EnumTrustDom
2218 static NTSTATUS dcesrv_lsa_EnumTrustDom(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2219 struct lsa_EnumTrustDom *r)
2221 struct dcesrv_handle *policy_handle;
2222 struct lsa_DomainInfo *entries;
2223 struct lsa_policy_state *policy_state;
2224 struct ldb_message **domains;
2225 const char *attrs[] = {
2226 "flatname",
2227 "securityIdentifier",
2228 NULL
2232 int count, i;
2234 *r->out.resume_handle = 0;
2236 r->out.domains->domains = NULL;
2237 r->out.domains->count = 0;
2239 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2241 policy_state = policy_handle->data;
2243 /* search for all users in this domain. This could possibly be cached and
2244 resumed based on resume_key */
2245 count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
2246 "objectclass=trustedDomain");
2247 if (count < 0) {
2248 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2251 /* convert to lsa_TrustInformation format */
2252 entries = talloc_array(mem_ctx, struct lsa_DomainInfo, count);
2253 if (!entries) {
2254 return NT_STATUS_NO_MEMORY;
2256 for (i=0;i<count;i++) {
2257 entries[i].sid = samdb_result_dom_sid(mem_ctx, domains[i], "securityIdentifier");
2258 entries[i].name.string = ldb_msg_find_attr_as_string(domains[i], "flatname", NULL);
2261 /* sort the results by name */
2262 TYPESAFE_QSORT(entries, count, compare_DomainInfo);
2264 if (*r->in.resume_handle >= count) {
2265 *r->out.resume_handle = -1;
2267 return NT_STATUS_NO_MORE_ENTRIES;
2270 /* return the rest, limit by max_size. Note that we
2271 use the w2k3 element size value of 60 */
2272 r->out.domains->count = count - *r->in.resume_handle;
2273 r->out.domains->count = MIN(r->out.domains->count,
2274 1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_MULTIPLIER));
2276 r->out.domains->domains = entries + *r->in.resume_handle;
2277 r->out.domains->count = r->out.domains->count;
2279 if (r->out.domains->count < count - *r->in.resume_handle) {
2280 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2281 return STATUS_MORE_ENTRIES;
2284 /* according to MS-LSAD 3.1.4.7.8 output resume handle MUST
2285 * always be larger than the previous input resume handle, in
2286 * particular when hitting the last query it is vital to set the
2287 * resume handle correctly to avoid infinite client loops, as
2288 * seen e.g. with Windows XP SP3 when resume handle is 0 and
2289 * status is NT_STATUS_OK - gd */
2291 *r->out.resume_handle = (uint32_t)-1;
2293 return NT_STATUS_OK;
2297 comparison function for sorting lsa_DomainInformation array
2299 static int compare_TrustDomainInfoInfoEx(struct lsa_TrustDomainInfoInfoEx *e1, struct lsa_TrustDomainInfoInfoEx *e2)
2301 return strcasecmp_m(e1->netbios_name.string, e2->netbios_name.string);
2305 lsa_EnumTrustedDomainsEx
2307 static NTSTATUS dcesrv_lsa_EnumTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2308 struct lsa_EnumTrustedDomainsEx *r)
2310 struct dcesrv_handle *policy_handle;
2311 struct lsa_TrustDomainInfoInfoEx *entries;
2312 struct lsa_policy_state *policy_state;
2313 struct ldb_message **domains;
2314 const char *attrs[] = {
2315 "flatname",
2316 "trustPartner",
2317 "securityIdentifier",
2318 "trustDirection",
2319 "trustType",
2320 "trustAttributes",
2321 NULL
2323 NTSTATUS nt_status;
2325 int count, i;
2327 *r->out.resume_handle = 0;
2329 r->out.domains->domains = NULL;
2330 r->out.domains->count = 0;
2332 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2334 policy_state = policy_handle->data;
2336 /* search for all users in this domain. This could possibly be cached and
2337 resumed based on resume_key */
2338 count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
2339 "objectclass=trustedDomain");
2340 if (count < 0) {
2341 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2344 /* convert to lsa_DomainInformation format */
2345 entries = talloc_array(mem_ctx, struct lsa_TrustDomainInfoInfoEx, count);
2346 if (!entries) {
2347 return NT_STATUS_NO_MEMORY;
2349 for (i=0;i<count;i++) {
2350 nt_status = fill_trust_domain_ex(mem_ctx, domains[i], &entries[i]);
2351 if (!NT_STATUS_IS_OK(nt_status)) {
2352 return nt_status;
2356 /* sort the results by name */
2357 TYPESAFE_QSORT(entries, count, compare_TrustDomainInfoInfoEx);
2359 if (*r->in.resume_handle >= count) {
2360 *r->out.resume_handle = -1;
2362 return NT_STATUS_NO_MORE_ENTRIES;
2365 /* return the rest, limit by max_size. Note that we
2366 use the w2k3 element size value of 60 */
2367 r->out.domains->count = count - *r->in.resume_handle;
2368 r->out.domains->count = MIN(r->out.domains->count,
2369 1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_EX_MULTIPLIER));
2371 r->out.domains->domains = entries + *r->in.resume_handle;
2372 r->out.domains->count = r->out.domains->count;
2374 if (r->out.domains->count < count - *r->in.resume_handle) {
2375 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2376 return STATUS_MORE_ENTRIES;
2379 return NT_STATUS_OK;
2384 lsa_OpenAccount
2386 static NTSTATUS dcesrv_lsa_OpenAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2387 struct lsa_OpenAccount *r)
2389 struct dcesrv_handle *h, *ah;
2390 struct lsa_policy_state *state;
2391 struct lsa_account_state *astate;
2393 ZERO_STRUCTP(r->out.acct_handle);
2395 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2397 state = h->data;
2399 astate = talloc(dce_call->conn, struct lsa_account_state);
2400 if (astate == NULL) {
2401 return NT_STATUS_NO_MEMORY;
2404 astate->account_sid = dom_sid_dup(astate, r->in.sid);
2405 if (astate->account_sid == NULL) {
2406 talloc_free(astate);
2407 return NT_STATUS_NO_MEMORY;
2410 astate->policy = talloc_reference(astate, state);
2411 astate->access_mask = r->in.access_mask;
2413 ah = dcesrv_handle_new(dce_call->context, LSA_HANDLE_ACCOUNT);
2414 if (!ah) {
2415 talloc_free(astate);
2416 return NT_STATUS_NO_MEMORY;
2419 ah->data = talloc_steal(ah, astate);
2421 *r->out.acct_handle = ah->wire_handle;
2423 return NT_STATUS_OK;
2428 lsa_EnumPrivsAccount
2430 static NTSTATUS dcesrv_lsa_EnumPrivsAccount(struct dcesrv_call_state *dce_call,
2431 TALLOC_CTX *mem_ctx,
2432 struct lsa_EnumPrivsAccount *r)
2434 struct dcesrv_handle *h;
2435 struct lsa_account_state *astate;
2436 int ret;
2437 unsigned int i, j;
2438 struct ldb_message **res;
2439 const char * const attrs[] = { "privilege", NULL};
2440 struct ldb_message_element *el;
2441 const char *sidstr;
2442 struct lsa_PrivilegeSet *privs;
2444 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2446 astate = h->data;
2448 privs = talloc(mem_ctx, struct lsa_PrivilegeSet);
2449 if (privs == NULL) {
2450 return NT_STATUS_NO_MEMORY;
2452 privs->count = 0;
2453 privs->unknown = 0;
2454 privs->set = NULL;
2456 *r->out.privs = privs;
2458 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
2459 if (sidstr == NULL) {
2460 return NT_STATUS_NO_MEMORY;
2463 ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs,
2464 "objectSid=%s", sidstr);
2465 if (ret < 0) {
2466 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2468 if (ret != 1) {
2469 return NT_STATUS_OK;
2472 el = ldb_msg_find_element(res[0], "privilege");
2473 if (el == NULL || el->num_values == 0) {
2474 return NT_STATUS_OK;
2477 privs->set = talloc_array(privs,
2478 struct lsa_LUIDAttribute, el->num_values);
2479 if (privs->set == NULL) {
2480 return NT_STATUS_NO_MEMORY;
2483 j = 0;
2484 for (i=0;i<el->num_values;i++) {
2485 int id = sec_privilege_id((const char *)el->values[i].data);
2486 if (id == SEC_PRIV_INVALID) {
2487 /* Perhaps an account right, not a privilege */
2488 continue;
2490 privs->set[j].attribute = 0;
2491 privs->set[j].luid.low = id;
2492 privs->set[j].luid.high = 0;
2493 j++;
2496 privs->count = j;
2498 return NT_STATUS_OK;
2502 lsa_EnumAccountRights
2504 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call,
2505 TALLOC_CTX *mem_ctx,
2506 struct lsa_EnumAccountRights *r)
2508 struct dcesrv_handle *h;
2509 struct lsa_policy_state *state;
2510 int ret;
2511 unsigned int i;
2512 struct ldb_message **res;
2513 const char * const attrs[] = { "privilege", NULL};
2514 const char *sidstr;
2515 struct ldb_message_element *el;
2517 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2519 state = h->data;
2521 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, r->in.sid);
2522 if (sidstr == NULL) {
2523 return NT_STATUS_NO_MEMORY;
2526 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
2527 "(&(objectSid=%s)(privilege=*))", sidstr);
2528 if (ret == 0) {
2529 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2531 if (ret != 1) {
2532 DEBUG(3, ("searching for account rights for SID: %s failed: %s",
2533 dom_sid_string(mem_ctx, r->in.sid),
2534 ldb_errstring(state->pdb)));
2535 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2538 el = ldb_msg_find_element(res[0], "privilege");
2539 if (el == NULL || el->num_values == 0) {
2540 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2543 r->out.rights->count = el->num_values;
2544 r->out.rights->names = talloc_array(r->out.rights,
2545 struct lsa_StringLarge, r->out.rights->count);
2546 if (r->out.rights->names == NULL) {
2547 return NT_STATUS_NO_MEMORY;
2550 for (i=0;i<el->num_values;i++) {
2551 r->out.rights->names[i].string = (const char *)el->values[i].data;
2554 return NT_STATUS_OK;
2560 helper for lsa_AddAccountRights and lsa_RemoveAccountRights
2562 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
2563 TALLOC_CTX *mem_ctx,
2564 struct lsa_policy_state *state,
2565 int ldb_flag,
2566 struct dom_sid *sid,
2567 const struct lsa_RightSet *rights)
2569 const char *sidstr, *sidndrstr;
2570 struct ldb_message *msg;
2571 struct ldb_message_element *el;
2572 int ret;
2573 uint32_t i;
2574 struct lsa_EnumAccountRights r2;
2575 char *dnstr;
2577 if (security_session_user_level(dce_call->conn->auth_state.session_info, NULL) <
2578 SECURITY_ADMINISTRATOR) {
2579 DEBUG(0,("lsa_AddRemoveAccount refused for supplied security token\n"));
2580 return NT_STATUS_ACCESS_DENIED;
2583 msg = ldb_msg_new(mem_ctx);
2584 if (msg == NULL) {
2585 return NT_STATUS_NO_MEMORY;
2588 sidndrstr = ldap_encode_ndr_dom_sid(msg, sid);
2589 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sidndrstr, msg);
2591 sidstr = dom_sid_string(msg, sid);
2592 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sidstr, msg);
2594 dnstr = talloc_asprintf(msg, "sid=%s", sidstr);
2595 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(dnstr, msg);
2597 msg->dn = ldb_dn_new(msg, state->pdb, dnstr);
2598 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(msg->dn, msg);
2600 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2601 NTSTATUS status;
2603 r2.in.handle = &state->handle->wire_handle;
2604 r2.in.sid = sid;
2605 r2.out.rights = talloc(mem_ctx, struct lsa_RightSet);
2607 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
2608 if (!NT_STATUS_IS_OK(status)) {
2609 ZERO_STRUCTP(r2.out.rights);
2613 for (i=0;i<rights->count;i++) {
2614 if (sec_privilege_id(rights->names[i].string) == SEC_PRIV_INVALID) {
2615 if (sec_right_bit(rights->names[i].string) == 0) {
2616 talloc_free(msg);
2617 return NT_STATUS_NO_SUCH_PRIVILEGE;
2620 talloc_free(msg);
2621 return NT_STATUS_NO_SUCH_PRIVILEGE;
2624 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2625 uint32_t j;
2626 for (j=0;j<r2.out.rights->count;j++) {
2627 if (strcasecmp_m(r2.out.rights->names[j].string,
2628 rights->names[i].string) == 0) {
2629 break;
2632 if (j != r2.out.rights->count) continue;
2635 ret = ldb_msg_add_string(msg, "privilege", rights->names[i].string);
2636 if (ret != LDB_SUCCESS) {
2637 talloc_free(msg);
2638 return NT_STATUS_NO_MEMORY;
2642 el = ldb_msg_find_element(msg, "privilege");
2643 if (!el) {
2644 talloc_free(msg);
2645 return NT_STATUS_OK;
2648 el->flags = ldb_flag;
2650 ret = ldb_modify(state->pdb, msg);
2651 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
2652 if (samdb_msg_add_dom_sid(state->pdb, msg, msg, "objectSid", sid) != LDB_SUCCESS) {
2653 talloc_free(msg);
2654 return NT_STATUS_NO_MEMORY;
2656 ldb_msg_add_string(msg, "comment", "added via LSA");
2657 ret = ldb_add(state->pdb, msg);
2659 if (ret != LDB_SUCCESS) {
2660 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE && ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
2661 talloc_free(msg);
2662 return NT_STATUS_OK;
2664 DEBUG(3, ("Could not %s attributes from %s: %s",
2665 LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE ? "delete" : "add",
2666 ldb_dn_get_linearized(msg->dn), ldb_errstring(state->pdb)));
2667 talloc_free(msg);
2668 return NT_STATUS_UNEXPECTED_IO_ERROR;
2671 talloc_free(msg);
2672 return NT_STATUS_OK;
2676 lsa_AddPrivilegesToAccount
2678 static NTSTATUS dcesrv_lsa_AddPrivilegesToAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2679 struct lsa_AddPrivilegesToAccount *r)
2681 struct lsa_RightSet rights;
2682 struct dcesrv_handle *h;
2683 struct lsa_account_state *astate;
2684 uint32_t i;
2686 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2688 astate = h->data;
2690 rights.count = r->in.privs->count;
2691 rights.names = talloc_array(mem_ctx, struct lsa_StringLarge, rights.count);
2692 if (rights.names == NULL) {
2693 return NT_STATUS_NO_MEMORY;
2695 for (i=0;i<rights.count;i++) {
2696 int id = r->in.privs->set[i].luid.low;
2697 if (r->in.privs->set[i].luid.high) {
2698 return NT_STATUS_NO_SUCH_PRIVILEGE;
2700 rights.names[i].string = sec_privilege_name(id);
2701 if (rights.names[i].string == NULL) {
2702 return NT_STATUS_NO_SUCH_PRIVILEGE;
2706 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
2707 LDB_FLAG_MOD_ADD, astate->account_sid,
2708 &rights);
2713 lsa_RemovePrivilegesFromAccount
2715 static NTSTATUS dcesrv_lsa_RemovePrivilegesFromAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2716 struct lsa_RemovePrivilegesFromAccount *r)
2718 struct lsa_RightSet *rights;
2719 struct dcesrv_handle *h;
2720 struct lsa_account_state *astate;
2721 uint32_t i;
2723 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2725 astate = h->data;
2727 rights = talloc(mem_ctx, struct lsa_RightSet);
2729 if (r->in.remove_all == 1 &&
2730 r->in.privs == NULL) {
2731 struct lsa_EnumAccountRights r2;
2732 NTSTATUS status;
2734 r2.in.handle = &astate->policy->handle->wire_handle;
2735 r2.in.sid = astate->account_sid;
2736 r2.out.rights = rights;
2738 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
2739 if (!NT_STATUS_IS_OK(status)) {
2740 return status;
2743 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
2744 LDB_FLAG_MOD_DELETE, astate->account_sid,
2745 r2.out.rights);
2748 if (r->in.remove_all != 0) {
2749 return NT_STATUS_INVALID_PARAMETER;
2752 rights->count = r->in.privs->count;
2753 rights->names = talloc_array(mem_ctx, struct lsa_StringLarge, rights->count);
2754 if (rights->names == NULL) {
2755 return NT_STATUS_NO_MEMORY;
2757 for (i=0;i<rights->count;i++) {
2758 int id = r->in.privs->set[i].luid.low;
2759 if (r->in.privs->set[i].luid.high) {
2760 return NT_STATUS_NO_SUCH_PRIVILEGE;
2762 rights->names[i].string = sec_privilege_name(id);
2763 if (rights->names[i].string == NULL) {
2764 return NT_STATUS_NO_SUCH_PRIVILEGE;
2768 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
2769 LDB_FLAG_MOD_DELETE, astate->account_sid,
2770 rights);
2775 lsa_GetQuotasForAccount
2777 static NTSTATUS dcesrv_lsa_GetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2778 struct lsa_GetQuotasForAccount *r)
2780 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2785 lsa_SetQuotasForAccount
2787 static NTSTATUS dcesrv_lsa_SetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2788 struct lsa_SetQuotasForAccount *r)
2790 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2795 lsa_GetSystemAccessAccount
2797 static NTSTATUS dcesrv_lsa_GetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2798 struct lsa_GetSystemAccessAccount *r)
2800 struct dcesrv_handle *h;
2801 struct lsa_account_state *astate;
2802 int ret;
2803 unsigned int i;
2804 struct ldb_message **res;
2805 const char * const attrs[] = { "privilege", NULL};
2806 struct ldb_message_element *el;
2807 const char *sidstr;
2809 *(r->out.access_mask) = 0x00000000;
2811 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2813 astate = h->data;
2815 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
2816 if (sidstr == NULL) {
2817 return NT_STATUS_NO_MEMORY;
2820 ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs,
2821 "objectSid=%s", sidstr);
2822 if (ret < 0) {
2823 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2825 if (ret != 1) {
2826 return NT_STATUS_OK;
2829 el = ldb_msg_find_element(res[0], "privilege");
2830 if (el == NULL || el->num_values == 0) {
2831 return NT_STATUS_OK;
2834 for (i=0;i<el->num_values;i++) {
2835 uint32_t right_bit = sec_right_bit((const char *)el->values[i].data);
2836 if (right_bit == 0) {
2837 /* Perhaps an privilege, not a right */
2838 continue;
2840 *(r->out.access_mask) |= right_bit;
2843 return NT_STATUS_OK;
2848 lsa_SetSystemAccessAccount
2850 static NTSTATUS dcesrv_lsa_SetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2851 struct lsa_SetSystemAccessAccount *r)
2853 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2858 lsa_CreateSecret
2860 static NTSTATUS dcesrv_lsa_CreateSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2861 struct lsa_CreateSecret *r)
2863 struct dcesrv_handle *policy_handle;
2864 struct lsa_policy_state *policy_state;
2865 struct lsa_secret_state *secret_state;
2866 struct dcesrv_handle *handle;
2867 struct ldb_message **msgs, *msg;
2868 const char *attrs[] = {
2869 NULL
2872 const char *name;
2874 int ret;
2876 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2877 ZERO_STRUCTP(r->out.sec_handle);
2879 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
2881 case SECURITY_SYSTEM:
2882 case SECURITY_ADMINISTRATOR:
2883 break;
2884 default:
2885 /* Users and annonymous are not allowed create secrets */
2886 return NT_STATUS_ACCESS_DENIED;
2889 policy_state = policy_handle->data;
2891 if (!r->in.name.string) {
2892 return NT_STATUS_INVALID_PARAMETER;
2895 secret_state = talloc(mem_ctx, struct lsa_secret_state);
2896 NT_STATUS_HAVE_NO_MEMORY(secret_state);
2897 secret_state->policy = policy_state;
2899 msg = ldb_msg_new(mem_ctx);
2900 if (msg == NULL) {
2901 return NT_STATUS_NO_MEMORY;
2904 if (strncmp("G$", r->in.name.string, 2) == 0) {
2905 const char *name2;
2907 secret_state->global = true;
2909 name = &r->in.name.string[2];
2910 if (strlen(name) == 0) {
2911 return NT_STATUS_INVALID_PARAMETER;
2914 name2 = talloc_asprintf(mem_ctx, "%s Secret",
2915 ldb_binary_encode_string(mem_ctx, name));
2916 NT_STATUS_HAVE_NO_MEMORY(name2);
2918 /* We need to connect to the database as system, as this is one
2919 * of the rare RPC calls that must read the secrets (and this
2920 * is denied otherwise) */
2921 secret_state->sam_ldb = talloc_reference(secret_state,
2922 samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(dce_call->conn->dce_ctx->lp_ctx), 0));
2923 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
2925 /* search for the secret record */
2926 ret = gendb_search(secret_state->sam_ldb,
2927 mem_ctx, policy_state->system_dn, &msgs, attrs,
2928 "(&(cn=%s)(objectclass=secret))",
2929 name2);
2930 if (ret > 0) {
2931 return NT_STATUS_OBJECT_NAME_COLLISION;
2934 if (ret < 0) {
2935 DEBUG(0,("Failure searching for CN=%s: %s\n",
2936 name2, ldb_errstring(secret_state->sam_ldb)));
2937 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2940 msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
2941 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
2942 if (!ldb_dn_add_child_fmt(msg->dn, "cn=%s", name2)) {
2943 return NT_STATUS_NO_MEMORY;
2946 ret = ldb_msg_add_string(msg, "cn", name2);
2947 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
2948 } else {
2949 secret_state->global = false;
2951 name = r->in.name.string;
2952 if (strlen(name) == 0) {
2953 return NT_STATUS_INVALID_PARAMETER;
2956 secret_state->sam_ldb = talloc_reference(secret_state,
2957 secrets_db_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
2958 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
2960 /* search for the secret record */
2961 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
2962 ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
2963 &msgs, attrs,
2964 "(&(cn=%s)(objectclass=secret))",
2965 ldb_binary_encode_string(mem_ctx, name));
2966 if (ret > 0) {
2967 return NT_STATUS_OBJECT_NAME_COLLISION;
2970 if (ret < 0) {
2971 DEBUG(0,("Failure searching for CN=%s: %s\n",
2972 name, ldb_errstring(secret_state->sam_ldb)));
2973 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2976 msg->dn = ldb_dn_new_fmt(mem_ctx, secret_state->sam_ldb,
2977 "cn=%s,cn=LSA Secrets", name);
2978 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
2979 ret = ldb_msg_add_string(msg, "cn", name);
2980 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
2983 ret = ldb_msg_add_string(msg, "objectClass", "secret");
2984 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
2986 secret_state->secret_dn = talloc_reference(secret_state, msg->dn);
2987 NT_STATUS_HAVE_NO_MEMORY(secret_state->secret_dn);
2989 /* create the secret */
2990 ret = ldb_add(secret_state->sam_ldb, msg);
2991 if (ret != LDB_SUCCESS) {
2992 DEBUG(0,("Failed to create secret record %s: %s\n",
2993 ldb_dn_get_linearized(msg->dn),
2994 ldb_errstring(secret_state->sam_ldb)));
2995 return NT_STATUS_ACCESS_DENIED;
2998 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
2999 NT_STATUS_HAVE_NO_MEMORY(handle);
3001 handle->data = talloc_steal(handle, secret_state);
3003 secret_state->access_mask = r->in.access_mask;
3004 secret_state->policy = talloc_reference(secret_state, policy_state);
3005 NT_STATUS_HAVE_NO_MEMORY(secret_state->policy);
3007 *r->out.sec_handle = handle->wire_handle;
3009 return NT_STATUS_OK;
3014 lsa_OpenSecret
3016 static NTSTATUS dcesrv_lsa_OpenSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3017 struct lsa_OpenSecret *r)
3019 struct dcesrv_handle *policy_handle;
3021 struct lsa_policy_state *policy_state;
3022 struct lsa_secret_state *secret_state;
3023 struct dcesrv_handle *handle;
3024 struct ldb_message **msgs;
3025 const char *attrs[] = {
3026 NULL
3029 const char *name;
3031 int ret;
3033 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
3034 ZERO_STRUCTP(r->out.sec_handle);
3035 policy_state = policy_handle->data;
3037 if (!r->in.name.string) {
3038 return NT_STATUS_INVALID_PARAMETER;
3041 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3043 case SECURITY_SYSTEM:
3044 case SECURITY_ADMINISTRATOR:
3045 break;
3046 default:
3047 /* Users and annonymous are not allowed to access secrets */
3048 return NT_STATUS_ACCESS_DENIED;
3051 secret_state = talloc(mem_ctx, struct lsa_secret_state);
3052 if (!secret_state) {
3053 return NT_STATUS_NO_MEMORY;
3055 secret_state->policy = policy_state;
3057 if (strncmp("G$", r->in.name.string, 2) == 0) {
3058 name = &r->in.name.string[2];
3059 /* We need to connect to the database as system, as this is one of the rare RPC calls that must read the secrets (and this is denied otherwise) */
3060 secret_state->sam_ldb = talloc_reference(secret_state,
3061 samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(dce_call->conn->dce_ctx->lp_ctx), 0));
3062 secret_state->global = true;
3064 if (strlen(name) < 1) {
3065 return NT_STATUS_INVALID_PARAMETER;
3068 /* search for the secret record */
3069 ret = gendb_search(secret_state->sam_ldb,
3070 mem_ctx, policy_state->system_dn, &msgs, attrs,
3071 "(&(cn=%s Secret)(objectclass=secret))",
3072 ldb_binary_encode_string(mem_ctx, name));
3073 if (ret == 0) {
3074 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3077 if (ret != 1) {
3078 DEBUG(0,("Found %d records matching DN %s\n", ret,
3079 ldb_dn_get_linearized(policy_state->system_dn)));
3080 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3082 } else {
3083 secret_state->global = false;
3084 secret_state->sam_ldb = talloc_reference(secret_state,
3085 secrets_db_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
3087 name = r->in.name.string;
3088 if (strlen(name) < 1) {
3089 return NT_STATUS_INVALID_PARAMETER;
3092 /* search for the secret record */
3093 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
3094 ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
3095 &msgs, attrs,
3096 "(&(cn=%s)(objectclass=secret))",
3097 ldb_binary_encode_string(mem_ctx, name));
3098 if (ret == 0) {
3099 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3102 if (ret != 1) {
3103 DEBUG(0,("Found %d records matching CN=%s\n",
3104 ret, ldb_binary_encode_string(mem_ctx, name)));
3105 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3109 secret_state->secret_dn = talloc_reference(secret_state, msgs[0]->dn);
3111 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
3112 if (!handle) {
3113 return NT_STATUS_NO_MEMORY;
3116 handle->data = talloc_steal(handle, secret_state);
3118 secret_state->access_mask = r->in.access_mask;
3119 secret_state->policy = talloc_reference(secret_state, policy_state);
3121 *r->out.sec_handle = handle->wire_handle;
3123 return NT_STATUS_OK;
3128 lsa_SetSecret
3130 static NTSTATUS dcesrv_lsa_SetSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3131 struct lsa_SetSecret *r)
3134 struct dcesrv_handle *h;
3135 struct lsa_secret_state *secret_state;
3136 struct ldb_message *msg;
3137 DATA_BLOB session_key;
3138 DATA_BLOB crypt_secret, secret;
3139 struct ldb_val val;
3140 int ret;
3141 NTSTATUS status = NT_STATUS_OK;
3143 struct timeval now = timeval_current();
3144 NTTIME nt_now = timeval_to_nttime(&now);
3146 DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3148 secret_state = h->data;
3150 msg = ldb_msg_new(mem_ctx);
3151 if (msg == NULL) {
3152 return NT_STATUS_NO_MEMORY;
3155 msg->dn = talloc_reference(mem_ctx, secret_state->secret_dn);
3156 if (!msg->dn) {
3157 return NT_STATUS_NO_MEMORY;
3159 status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
3160 if (!NT_STATUS_IS_OK(status)) {
3161 return status;
3164 if (r->in.old_val) {
3165 /* Decrypt */
3166 crypt_secret.data = r->in.old_val->data;
3167 crypt_secret.length = r->in.old_val->size;
3169 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3170 if (!NT_STATUS_IS_OK(status)) {
3171 return status;
3174 val.data = secret.data;
3175 val.length = secret.length;
3177 /* set value */
3178 if (ldb_msg_add_value(msg, "priorValue", &val, NULL) != LDB_SUCCESS) {
3179 return NT_STATUS_NO_MEMORY;
3182 /* set old value mtime */
3183 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3184 mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3185 return NT_STATUS_NO_MEMORY;
3188 } else {
3189 /* If the old value is not set, then migrate the
3190 * current value to the old value */
3191 const struct ldb_val *old_val;
3192 NTTIME last_set_time;
3193 struct ldb_message **res;
3194 const char *attrs[] = {
3195 "currentValue",
3196 "lastSetTime",
3197 NULL
3200 /* search for the secret record */
3201 ret = gendb_search_dn(secret_state->sam_ldb,mem_ctx,
3202 secret_state->secret_dn, &res, attrs);
3203 if (ret == 0) {
3204 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3207 if (ret != 1) {
3208 DEBUG(0,("Found %d records matching dn=%s\n", ret,
3209 ldb_dn_get_linearized(secret_state->secret_dn)));
3210 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3213 old_val = ldb_msg_find_ldb_val(res[0], "currentValue");
3214 last_set_time = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
3216 if (old_val) {
3217 /* set old value */
3218 if (ldb_msg_add_value(msg, "priorValue",
3219 old_val, NULL) != LDB_SUCCESS) {
3220 return NT_STATUS_NO_MEMORY;
3222 } else {
3223 if (samdb_msg_add_delete(secret_state->sam_ldb,
3224 mem_ctx, msg, "priorValue") != LDB_SUCCESS) {
3225 return NT_STATUS_NO_MEMORY;
3229 /* set old value mtime */
3230 if (ldb_msg_find_ldb_val(res[0], "lastSetTime")) {
3231 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3232 mem_ctx, msg, "priorSetTime", last_set_time) != LDB_SUCCESS) {
3233 return NT_STATUS_NO_MEMORY;
3235 } else {
3236 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3237 mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3238 return NT_STATUS_NO_MEMORY;
3243 if (r->in.new_val) {
3244 /* Decrypt */
3245 crypt_secret.data = r->in.new_val->data;
3246 crypt_secret.length = r->in.new_val->size;
3248 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3249 if (!NT_STATUS_IS_OK(status)) {
3250 return status;
3253 val.data = secret.data;
3254 val.length = secret.length;
3256 /* set value */
3257 if (ldb_msg_add_value(msg, "currentValue", &val, NULL) != LDB_SUCCESS) {
3258 return NT_STATUS_NO_MEMORY;
3261 /* set new value mtime */
3262 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3263 mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3264 return NT_STATUS_NO_MEMORY;
3266 } else {
3267 /* NULL out the NEW value */
3268 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3269 mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3270 return NT_STATUS_NO_MEMORY;
3272 if (samdb_msg_add_delete(secret_state->sam_ldb,
3273 mem_ctx, msg, "currentValue") != LDB_SUCCESS) {
3274 return NT_STATUS_NO_MEMORY;
3278 /* modify the samdb record */
3279 ret = dsdb_replace(secret_state->sam_ldb, msg, 0);
3280 if (ret != LDB_SUCCESS) {
3281 return dsdb_ldb_err_to_ntstatus(ret);
3284 return NT_STATUS_OK;
3289 lsa_QuerySecret
3291 static NTSTATUS dcesrv_lsa_QuerySecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3292 struct lsa_QuerySecret *r)
3294 struct dcesrv_handle *h;
3295 struct lsa_secret_state *secret_state;
3296 struct ldb_message *msg;
3297 DATA_BLOB session_key;
3298 DATA_BLOB crypt_secret, secret;
3299 int ret;
3300 struct ldb_message **res;
3301 const char *attrs[] = {
3302 "currentValue",
3303 "priorValue",
3304 "lastSetTime",
3305 "priorSetTime",
3306 NULL
3309 NTSTATUS nt_status;
3311 DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3313 /* Ensure user is permitted to read this... */
3314 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3316 case SECURITY_SYSTEM:
3317 case SECURITY_ADMINISTRATOR:
3318 break;
3319 default:
3320 /* Users and annonymous are not allowed to read secrets */
3321 return NT_STATUS_ACCESS_DENIED;
3324 secret_state = h->data;
3326 /* pull all the user attributes */
3327 ret = gendb_search_dn(secret_state->sam_ldb, mem_ctx,
3328 secret_state->secret_dn, &res, attrs);
3329 if (ret != 1) {
3330 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3332 msg = res[0];
3334 nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
3335 if (!NT_STATUS_IS_OK(nt_status)) {
3336 return nt_status;
3339 if (r->in.old_val) {
3340 const struct ldb_val *prior_val;
3341 r->out.old_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3342 if (!r->out.old_val) {
3343 return NT_STATUS_NO_MEMORY;
3345 prior_val = ldb_msg_find_ldb_val(res[0], "priorValue");
3347 if (prior_val && prior_val->length) {
3348 secret.data = prior_val->data;
3349 secret.length = prior_val->length;
3351 /* Encrypt */
3352 crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3353 if (!crypt_secret.length) {
3354 return NT_STATUS_NO_MEMORY;
3356 r->out.old_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3357 if (!r->out.old_val->buf) {
3358 return NT_STATUS_NO_MEMORY;
3360 r->out.old_val->buf->size = crypt_secret.length;
3361 r->out.old_val->buf->length = crypt_secret.length;
3362 r->out.old_val->buf->data = crypt_secret.data;
3366 if (r->in.old_mtime) {
3367 r->out.old_mtime = talloc(mem_ctx, NTTIME);
3368 if (!r->out.old_mtime) {
3369 return NT_STATUS_NO_MEMORY;
3371 *r->out.old_mtime = ldb_msg_find_attr_as_uint64(res[0], "priorSetTime", 0);
3374 if (r->in.new_val) {
3375 const struct ldb_val *new_val;
3376 r->out.new_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3377 if (!r->out.new_val) {
3378 return NT_STATUS_NO_MEMORY;
3381 new_val = ldb_msg_find_ldb_val(res[0], "currentValue");
3383 if (new_val && new_val->length) {
3384 secret.data = new_val->data;
3385 secret.length = new_val->length;
3387 /* Encrypt */
3388 crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3389 if (!crypt_secret.length) {
3390 return NT_STATUS_NO_MEMORY;
3392 r->out.new_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3393 if (!r->out.new_val->buf) {
3394 return NT_STATUS_NO_MEMORY;
3396 r->out.new_val->buf->length = crypt_secret.length;
3397 r->out.new_val->buf->size = crypt_secret.length;
3398 r->out.new_val->buf->data = crypt_secret.data;
3402 if (r->in.new_mtime) {
3403 r->out.new_mtime = talloc(mem_ctx, NTTIME);
3404 if (!r->out.new_mtime) {
3405 return NT_STATUS_NO_MEMORY;
3407 *r->out.new_mtime = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
3410 return NT_STATUS_OK;
3415 lsa_LookupPrivValue
3417 static NTSTATUS dcesrv_lsa_LookupPrivValue(struct dcesrv_call_state *dce_call,
3418 TALLOC_CTX *mem_ctx,
3419 struct lsa_LookupPrivValue *r)
3421 struct dcesrv_handle *h;
3422 int id;
3424 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3426 id = sec_privilege_id(r->in.name->string);
3427 if (id == SEC_PRIV_INVALID) {
3428 return NT_STATUS_NO_SUCH_PRIVILEGE;
3431 r->out.luid->low = id;
3432 r->out.luid->high = 0;
3434 return NT_STATUS_OK;
3439 lsa_LookupPrivName
3441 static NTSTATUS dcesrv_lsa_LookupPrivName(struct dcesrv_call_state *dce_call,
3442 TALLOC_CTX *mem_ctx,
3443 struct lsa_LookupPrivName *r)
3445 struct dcesrv_handle *h;
3446 struct lsa_StringLarge *name;
3447 const char *privname;
3449 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3451 if (r->in.luid->high != 0) {
3452 return NT_STATUS_NO_SUCH_PRIVILEGE;
3455 privname = sec_privilege_name(r->in.luid->low);
3456 if (privname == NULL) {
3457 return NT_STATUS_NO_SUCH_PRIVILEGE;
3460 name = talloc(mem_ctx, struct lsa_StringLarge);
3461 if (name == NULL) {
3462 return NT_STATUS_NO_MEMORY;
3465 name->string = privname;
3467 *r->out.name = name;
3469 return NT_STATUS_OK;
3474 lsa_LookupPrivDisplayName
3476 static NTSTATUS dcesrv_lsa_LookupPrivDisplayName(struct dcesrv_call_state *dce_call,
3477 TALLOC_CTX *mem_ctx,
3478 struct lsa_LookupPrivDisplayName *r)
3480 struct dcesrv_handle *h;
3481 struct lsa_StringLarge *disp_name = NULL;
3482 enum sec_privilege id;
3484 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3486 id = sec_privilege_id(r->in.name->string);
3487 if (id == SEC_PRIV_INVALID) {
3488 return NT_STATUS_NO_SUCH_PRIVILEGE;
3491 disp_name = talloc(mem_ctx, struct lsa_StringLarge);
3492 if (disp_name == NULL) {
3493 return NT_STATUS_NO_MEMORY;
3496 disp_name->string = sec_privilege_display_name(id, &r->in.language_id);
3497 if (disp_name->string == NULL) {
3498 return NT_STATUS_INTERNAL_ERROR;
3501 *r->out.disp_name = disp_name;
3502 *r->out.returned_language_id = 0;
3504 return NT_STATUS_OK;
3509 lsa_EnumAccountsWithUserRight
3511 static NTSTATUS dcesrv_lsa_EnumAccountsWithUserRight(struct dcesrv_call_state *dce_call,
3512 TALLOC_CTX *mem_ctx,
3513 struct lsa_EnumAccountsWithUserRight *r)
3515 struct dcesrv_handle *h;
3516 struct lsa_policy_state *state;
3517 int ret, i;
3518 struct ldb_message **res;
3519 const char * const attrs[] = { "objectSid", NULL};
3520 const char *privname;
3522 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3524 state = h->data;
3526 if (r->in.name == NULL) {
3527 return NT_STATUS_NO_SUCH_PRIVILEGE;
3530 privname = r->in.name->string;
3531 if (sec_privilege_id(privname) == SEC_PRIV_INVALID && sec_right_bit(privname) == 0) {
3532 return NT_STATUS_NO_SUCH_PRIVILEGE;
3535 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
3536 "privilege=%s", privname);
3537 if (ret < 0) {
3538 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3540 if (ret == 0) {
3541 return NT_STATUS_NO_MORE_ENTRIES;
3544 r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, ret);
3545 if (r->out.sids->sids == NULL) {
3546 return NT_STATUS_NO_MEMORY;
3548 for (i=0;i<ret;i++) {
3549 r->out.sids->sids[i].sid = samdb_result_dom_sid(r->out.sids->sids,
3550 res[i], "objectSid");
3551 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
3553 r->out.sids->num_sids = ret;
3555 return NT_STATUS_OK;
3560 lsa_AddAccountRights
3562 static NTSTATUS dcesrv_lsa_AddAccountRights(struct dcesrv_call_state *dce_call,
3563 TALLOC_CTX *mem_ctx,
3564 struct lsa_AddAccountRights *r)
3566 struct dcesrv_handle *h;
3567 struct lsa_policy_state *state;
3569 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3571 state = h->data;
3573 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3574 LDB_FLAG_MOD_ADD,
3575 r->in.sid, r->in.rights);
3580 lsa_RemoveAccountRights
3582 static NTSTATUS dcesrv_lsa_RemoveAccountRights(struct dcesrv_call_state *dce_call,
3583 TALLOC_CTX *mem_ctx,
3584 struct lsa_RemoveAccountRights *r)
3586 struct dcesrv_handle *h;
3587 struct lsa_policy_state *state;
3589 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3591 state = h->data;
3593 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3594 LDB_FLAG_MOD_DELETE,
3595 r->in.sid, r->in.rights);
3600 lsa_StorePrivateData
3602 static NTSTATUS dcesrv_lsa_StorePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3603 struct lsa_StorePrivateData *r)
3605 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3610 lsa_RetrievePrivateData
3612 static NTSTATUS dcesrv_lsa_RetrievePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3613 struct lsa_RetrievePrivateData *r)
3615 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3620 lsa_GetUserName
3622 static NTSTATUS dcesrv_lsa_GetUserName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3623 struct lsa_GetUserName *r)
3625 enum dcerpc_transport_t transport = dce_call->conn->endpoint->ep_description->transport;
3626 NTSTATUS status = NT_STATUS_OK;
3627 const char *account_name;
3628 const char *authority_name;
3629 struct lsa_String *_account_name;
3630 struct lsa_String *_authority_name = NULL;
3632 if (transport != NCACN_NP && transport != NCALRPC) {
3633 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
3636 /* this is what w2k3 does */
3637 r->out.account_name = r->in.account_name;
3638 r->out.authority_name = r->in.authority_name;
3640 if (r->in.account_name
3641 && *r->in.account_name
3642 /* && *(*r->in.account_name)->string */
3644 return NT_STATUS_INVALID_PARAMETER;
3647 if (r->in.authority_name
3648 && *r->in.authority_name
3649 /* && *(*r->in.authority_name)->string */
3651 return NT_STATUS_INVALID_PARAMETER;
3654 account_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->info->account_name);
3655 authority_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->info->domain_name);
3657 _account_name = talloc(mem_ctx, struct lsa_String);
3658 NT_STATUS_HAVE_NO_MEMORY(_account_name);
3659 _account_name->string = account_name;
3661 if (r->in.authority_name) {
3662 _authority_name = talloc(mem_ctx, struct lsa_String);
3663 NT_STATUS_HAVE_NO_MEMORY(_authority_name);
3664 _authority_name->string = authority_name;
3667 *r->out.account_name = _account_name;
3668 if (r->out.authority_name) {
3669 *r->out.authority_name = _authority_name;
3672 return status;
3676 lsa_SetInfoPolicy2
3678 static NTSTATUS dcesrv_lsa_SetInfoPolicy2(struct dcesrv_call_state *dce_call,
3679 TALLOC_CTX *mem_ctx,
3680 struct lsa_SetInfoPolicy2 *r)
3682 /* need to support these */
3683 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3686 static void kdc_get_policy(struct loadparm_context *lp_ctx,
3687 struct smb_krb5_context *smb_krb5_context,
3688 struct lsa_DomainInfoKerberos *k)
3690 time_t svc_tkt_lifetime;
3691 time_t usr_tkt_lifetime;
3692 time_t renewal_lifetime;
3694 /* These should be set and stored via Group Policy, but until then, some defaults are in order */
3696 /* Our KDC always re-validates the client */
3697 k->authentication_options = LSA_POLICY_KERBEROS_VALIDATE_CLIENT;
3699 lpcfg_default_kdc_policy(lp_ctx, &svc_tkt_lifetime,
3700 &usr_tkt_lifetime, &renewal_lifetime);
3702 unix_to_nt_time(&k->service_tkt_lifetime, svc_tkt_lifetime);
3703 unix_to_nt_time(&k->user_tkt_lifetime, usr_tkt_lifetime);
3704 unix_to_nt_time(&k->user_tkt_renewaltime, renewal_lifetime);
3705 #ifdef SAMBA4_USES_HEIMDAL /* MIT lacks krb5_get_max_time_skew.
3706 However in the parent function we basically just did a full
3707 krb5_context init with the only purpose of getting a global
3708 config option (the max skew), it would probably make more sense
3709 to have a lp_ or ldb global option as the samba default */
3710 if (smb_krb5_context) {
3711 unix_to_nt_time(&k->clock_skew,
3712 krb5_get_max_time_skew(smb_krb5_context->krb5_context));
3714 #endif
3715 k->reserved = 0;
3718 lsa_QueryDomainInformationPolicy
3720 static NTSTATUS dcesrv_lsa_QueryDomainInformationPolicy(struct dcesrv_call_state *dce_call,
3721 TALLOC_CTX *mem_ctx,
3722 struct lsa_QueryDomainInformationPolicy *r)
3724 union lsa_DomainInformationPolicy *info;
3726 info = talloc_zero(r->out.info, union lsa_DomainInformationPolicy);
3727 if (!info) {
3728 return NT_STATUS_NO_MEMORY;
3731 switch (r->in.level) {
3732 case LSA_DOMAIN_INFO_POLICY_EFS:
3733 talloc_free(info);
3734 *r->out.info = NULL;
3735 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3736 case LSA_DOMAIN_INFO_POLICY_KERBEROS:
3738 struct lsa_DomainInfoKerberos *k = &info->kerberos_info;
3739 struct smb_krb5_context *smb_krb5_context;
3740 int ret = smb_krb5_init_context(mem_ctx,
3741 dce_call->event_ctx,
3742 dce_call->conn->dce_ctx->lp_ctx,
3743 &smb_krb5_context);
3744 if (ret != 0) {
3745 talloc_free(info);
3746 *r->out.info = NULL;
3747 return NT_STATUS_INTERNAL_ERROR;
3749 kdc_get_policy(dce_call->conn->dce_ctx->lp_ctx,
3750 smb_krb5_context,
3752 talloc_free(smb_krb5_context);
3753 *r->out.info = info;
3754 return NT_STATUS_OK;
3756 default:
3757 talloc_free(info);
3758 *r->out.info = NULL;
3759 return NT_STATUS_INVALID_INFO_CLASS;
3764 lsa_SetDomInfoPolicy
3766 static NTSTATUS dcesrv_lsa_SetDomainInformationPolicy(struct dcesrv_call_state *dce_call,
3767 TALLOC_CTX *mem_ctx,
3768 struct lsa_SetDomainInformationPolicy *r)
3770 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3774 lsa_TestCall
3776 static NTSTATUS dcesrv_lsa_TestCall(struct dcesrv_call_state *dce_call,
3777 TALLOC_CTX *mem_ctx,
3778 struct lsa_TestCall *r)
3780 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3784 lsa_CREDRWRITE
3786 static NTSTATUS dcesrv_lsa_CREDRWRITE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3787 struct lsa_CREDRWRITE *r)
3789 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3794 lsa_CREDRREAD
3796 static NTSTATUS dcesrv_lsa_CREDRREAD(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3797 struct lsa_CREDRREAD *r)
3799 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3804 lsa_CREDRENUMERATE
3806 static NTSTATUS dcesrv_lsa_CREDRENUMERATE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3807 struct lsa_CREDRENUMERATE *r)
3809 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3814 lsa_CREDRWRITEDOMAINCREDENTIALS
3816 static NTSTATUS dcesrv_lsa_CREDRWRITEDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3817 struct lsa_CREDRWRITEDOMAINCREDENTIALS *r)
3819 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3824 lsa_CREDRREADDOMAINCREDENTIALS
3826 static NTSTATUS dcesrv_lsa_CREDRREADDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3827 struct lsa_CREDRREADDOMAINCREDENTIALS *r)
3829 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3834 lsa_CREDRDELETE
3836 static NTSTATUS dcesrv_lsa_CREDRDELETE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3837 struct lsa_CREDRDELETE *r)
3839 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3844 lsa_CREDRGETTARGETINFO
3846 static NTSTATUS dcesrv_lsa_CREDRGETTARGETINFO(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3847 struct lsa_CREDRGETTARGETINFO *r)
3849 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3854 lsa_CREDRPROFILELOADED
3856 static NTSTATUS dcesrv_lsa_CREDRPROFILELOADED(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3857 struct lsa_CREDRPROFILELOADED *r)
3859 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3864 lsa_CREDRGETSESSIONTYPES
3866 static NTSTATUS dcesrv_lsa_CREDRGETSESSIONTYPES(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3867 struct lsa_CREDRGETSESSIONTYPES *r)
3869 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3874 lsa_LSARREGISTERAUDITEVENT
3876 static NTSTATUS dcesrv_lsa_LSARREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3877 struct lsa_LSARREGISTERAUDITEVENT *r)
3879 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3884 lsa_LSARGENAUDITEVENT
3886 static NTSTATUS dcesrv_lsa_LSARGENAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3887 struct lsa_LSARGENAUDITEVENT *r)
3889 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3894 lsa_LSARUNREGISTERAUDITEVENT
3896 static NTSTATUS dcesrv_lsa_LSARUNREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3897 struct lsa_LSARUNREGISTERAUDITEVENT *r)
3899 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3904 lsa_lsaRQueryForestTrustInformation
3906 static NTSTATUS dcesrv_lsa_lsaRQueryForestTrustInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3907 struct lsa_lsaRQueryForestTrustInformation *r)
3909 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3912 #define DNS_CMP_MATCH 0
3913 #define DNS_CMP_FIRST_IS_CHILD 1
3914 #define DNS_CMP_SECOND_IS_CHILD 2
3915 #define DNS_CMP_NO_MATCH 3
3917 /* this function assumes names are well formed DNS names.
3918 * it doesn't validate them */
3919 static int dns_cmp(const char *s1, size_t l1,
3920 const char *s2, size_t l2)
3922 const char *p1, *p2;
3923 size_t t1, t2;
3924 int cret;
3926 if (l1 == l2) {
3927 if (strcasecmp_m(s1, s2) == 0) {
3928 return DNS_CMP_MATCH;
3930 return DNS_CMP_NO_MATCH;
3933 if (l1 > l2) {
3934 p1 = s1;
3935 p2 = s2;
3936 t1 = l1;
3937 t2 = l2;
3938 cret = DNS_CMP_FIRST_IS_CHILD;
3939 } else {
3940 p1 = s2;
3941 p2 = s1;
3942 t1 = l2;
3943 t2 = l1;
3944 cret = DNS_CMP_SECOND_IS_CHILD;
3947 if (p1[t1 - t2 - 1] != '.') {
3948 return DNS_CMP_NO_MATCH;
3951 if (strcasecmp_m(&p1[t1 - t2], p2) == 0) {
3952 return cret;
3955 return DNS_CMP_NO_MATCH;
3958 /* decode all TDOs forest trust info blobs */
3959 static NTSTATUS get_ft_info(TALLOC_CTX *mem_ctx,
3960 struct ldb_message *msg,
3961 struct ForestTrustInfo *info)
3963 const struct ldb_val *ft_blob;
3964 enum ndr_err_code ndr_err;
3966 ft_blob = ldb_msg_find_ldb_val(msg, "msDS-TrustForestTrustInfo");
3967 if (!ft_blob || !ft_blob->data) {
3968 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3970 /* ldb_val is equivalent to DATA_BLOB */
3971 ndr_err = ndr_pull_struct_blob_all(ft_blob, mem_ctx, info,
3972 (ndr_pull_flags_fn_t)ndr_pull_ForestTrustInfo);
3973 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
3974 return NT_STATUS_INVALID_DOMAIN_STATE;
3977 return NT_STATUS_OK;
3980 static NTSTATUS own_ft_info(struct lsa_policy_state *ps,
3981 struct ForestTrustInfo *fti)
3983 struct ForestTrustDataDomainInfo *info;
3984 struct ForestTrustInfoRecord *rec;
3986 fti->version = 1;
3987 fti->count = 2;
3988 fti->records = talloc_array(fti,
3989 struct ForestTrustInfoRecordArmor, 2);
3990 if (!fti->records) {
3991 return NT_STATUS_NO_MEMORY;
3994 /* TLN info */
3995 rec = &fti->records[0].record;
3997 rec->flags = 0;
3998 rec->timestamp = 0;
3999 rec->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
4001 rec->data.name.string = talloc_strdup(fti, ps->forest_dns);
4002 if (!rec->data.name.string) {
4003 return NT_STATUS_NO_MEMORY;
4005 rec->data.name.size = strlen(rec->data.name.string);
4007 /* DOMAIN info */
4008 rec = &fti->records[1].record;
4010 rec->flags = 0;
4011 rec->timestamp = 0;
4012 rec->type = LSA_FOREST_TRUST_DOMAIN_INFO;
4014 info = &rec->data.info;
4016 info->sid = *ps->domain_sid;
4017 info->dns_name.string = talloc_strdup(fti, ps->domain_dns);
4018 if (!info->dns_name.string) {
4019 return NT_STATUS_NO_MEMORY;
4021 info->dns_name.size = strlen(info->dns_name.string);
4022 info->netbios_name.string = talloc_strdup(fti, ps->domain_name);
4023 if (!info->netbios_name.string) {
4024 return NT_STATUS_NO_MEMORY;
4026 info->netbios_name.size = strlen(info->netbios_name.string);
4028 return NT_STATUS_OK;
4031 static NTSTATUS make_ft_info(TALLOC_CTX *mem_ctx,
4032 struct lsa_ForestTrustInformation *lfti,
4033 struct ForestTrustInfo *fti)
4035 struct lsa_ForestTrustRecord *lrec;
4036 struct ForestTrustInfoRecord *rec;
4037 struct lsa_StringLarge *tln;
4038 struct lsa_ForestTrustDomainInfo *info;
4039 uint32_t i;
4041 fti->version = 1;
4042 fti->count = lfti->count;
4043 fti->records = talloc_array(mem_ctx,
4044 struct ForestTrustInfoRecordArmor,
4045 fti->count);
4046 if (!fti->records) {
4047 return NT_STATUS_NO_MEMORY;
4049 for (i = 0; i < fti->count; i++) {
4050 lrec = lfti->entries[i];
4051 rec = &fti->records[i].record;
4053 rec->flags = lrec->flags;
4054 rec->timestamp = lrec->time;
4055 rec->type = lrec->type;
4057 switch (lrec->type) {
4058 case LSA_FOREST_TRUST_TOP_LEVEL_NAME:
4059 case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
4060 tln = &lrec->forest_trust_data.top_level_name;
4061 rec->data.name.string =
4062 talloc_strdup(mem_ctx, tln->string);
4063 if (!rec->data.name.string) {
4064 return NT_STATUS_NO_MEMORY;
4066 rec->data.name.size = strlen(rec->data.name.string);
4067 break;
4068 case LSA_FOREST_TRUST_DOMAIN_INFO:
4069 info = &lrec->forest_trust_data.domain_info;
4070 rec->data.info.sid = *info->domain_sid;
4071 rec->data.info.dns_name.string =
4072 talloc_strdup(mem_ctx,
4073 info->dns_domain_name.string);
4074 if (!rec->data.info.dns_name.string) {
4075 return NT_STATUS_NO_MEMORY;
4077 rec->data.info.dns_name.size =
4078 strlen(rec->data.info.dns_name.string);
4079 rec->data.info.netbios_name.string =
4080 talloc_strdup(mem_ctx,
4081 info->netbios_domain_name.string);
4082 if (!rec->data.info.netbios_name.string) {
4083 return NT_STATUS_NO_MEMORY;
4085 rec->data.info.netbios_name.size =
4086 strlen(rec->data.info.netbios_name.string);
4087 break;
4088 default:
4089 return NT_STATUS_INVALID_DOMAIN_STATE;
4093 return NT_STATUS_OK;
4096 static NTSTATUS add_collision(struct lsa_ForestTrustCollisionInfo *c_info,
4097 uint32_t idx, uint32_t collision_type,
4098 uint32_t conflict_type, const char *tdo_name);
4100 static NTSTATUS check_ft_info(TALLOC_CTX *mem_ctx,
4101 const char *tdo_name,
4102 struct ForestTrustInfo *tdo_fti,
4103 struct ForestTrustInfo *new_fti,
4104 struct lsa_ForestTrustCollisionInfo *c_info)
4106 struct ForestTrustInfoRecord *nrec;
4107 struct ForestTrustInfoRecord *trec;
4108 const char *dns_name;
4109 const char *nb_name;
4110 struct dom_sid *sid;
4111 const char *tname;
4112 size_t dns_len;
4113 size_t tlen;
4114 NTSTATUS nt_status = NT_STATUS_OK;
4115 uint32_t new_fti_idx;
4116 uint32_t i;
4117 /* use always TDO type, until we understand when Xref can be used */
4118 uint32_t collision_type = LSA_FOREST_TRUST_COLLISION_TDO;
4119 bool tln_conflict;
4120 bool sid_conflict;
4121 bool nb_conflict;
4122 bool exclusion;
4123 bool ex_rule;
4124 int ret;
4126 for (new_fti_idx = 0; new_fti_idx < new_fti->count; new_fti_idx++) {
4128 nrec = &new_fti->records[new_fti_idx].record;
4129 dns_name = NULL;
4130 tln_conflict = false;
4131 sid_conflict = false;
4132 nb_conflict = false;
4133 exclusion = false;
4135 switch (nrec->type) {
4136 case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
4137 /* exclusions do not conflict by definition */
4138 break;
4140 case FOREST_TRUST_TOP_LEVEL_NAME:
4141 dns_name = nrec->data.name.string;
4142 dns_len = nrec->data.name.size;
4143 break;
4145 case LSA_FOREST_TRUST_DOMAIN_INFO:
4146 dns_name = nrec->data.info.dns_name.string;
4147 dns_len = nrec->data.info.dns_name.size;
4148 nb_name = nrec->data.info.netbios_name.string;
4149 sid = &nrec->data.info.sid;
4150 break;
4153 if (!dns_name) continue;
4155 /* check if this is already taken and not excluded */
4156 for (i = 0; i < tdo_fti->count; i++) {
4157 trec = &tdo_fti->records[i].record;
4159 switch (trec->type) {
4160 case FOREST_TRUST_TOP_LEVEL_NAME:
4161 ex_rule = false;
4162 tname = trec->data.name.string;
4163 tlen = trec->data.name.size;
4164 break;
4165 case FOREST_TRUST_TOP_LEVEL_NAME_EX:
4166 ex_rule = true;
4167 tname = trec->data.name.string;
4168 tlen = trec->data.name.size;
4169 break;
4170 case FOREST_TRUST_DOMAIN_INFO:
4171 ex_rule = false;
4172 tname = trec->data.info.dns_name.string;
4173 tlen = trec->data.info.dns_name.size;
4175 ret = dns_cmp(dns_name, dns_len, tname, tlen);
4176 switch (ret) {
4177 case DNS_CMP_MATCH:
4178 /* if it matches exclusion,
4179 * it doesn't conflict */
4180 if (ex_rule) {
4181 exclusion = true;
4182 break;
4184 /* fall through */
4185 case DNS_CMP_FIRST_IS_CHILD:
4186 case DNS_CMP_SECOND_IS_CHILD:
4187 tln_conflict = true;
4188 /* fall through */
4189 default:
4190 break;
4193 /* explicit exclusion, no dns name conflict here */
4194 if (exclusion) {
4195 tln_conflict = false;
4198 if (trec->type != FOREST_TRUST_DOMAIN_INFO) {
4199 continue;
4202 /* also test for domain info */
4203 if (!(trec->flags & LSA_SID_DISABLED_ADMIN) &&
4204 dom_sid_compare(&trec->data.info.sid, sid) == 0) {
4205 sid_conflict = true;
4207 if (!(trec->flags & LSA_NB_DISABLED_ADMIN) &&
4208 strcasecmp_m(trec->data.info.netbios_name.string,
4209 nb_name) == 0) {
4210 nb_conflict = true;
4214 if (tln_conflict) {
4215 nt_status = add_collision(c_info, new_fti_idx,
4216 collision_type,
4217 LSA_TLN_DISABLED_CONFLICT,
4218 tdo_name);
4219 if (!NT_STATUS_IS_OK(nt_status)) {
4220 goto done;
4223 if (sid_conflict) {
4224 nt_status = add_collision(c_info, new_fti_idx,
4225 collision_type,
4226 LSA_SID_DISABLED_CONFLICT,
4227 tdo_name);
4228 if (!NT_STATUS_IS_OK(nt_status)) {
4229 goto done;
4232 if (nb_conflict) {
4233 nt_status = add_collision(c_info, new_fti_idx,
4234 collision_type,
4235 LSA_NB_DISABLED_CONFLICT,
4236 tdo_name);
4237 if (!NT_STATUS_IS_OK(nt_status)) {
4238 goto done;
4243 done:
4244 return nt_status;
4247 static NTSTATUS add_collision(struct lsa_ForestTrustCollisionInfo *c_info,
4248 uint32_t idx, uint32_t collision_type,
4249 uint32_t conflict_type, const char *tdo_name)
4251 struct lsa_ForestTrustCollisionRecord **es;
4252 uint32_t i = c_info->count;
4254 es = talloc_realloc(c_info, c_info->entries,
4255 struct lsa_ForestTrustCollisionRecord *, i + 1);
4256 if (!es) {
4257 return NT_STATUS_NO_MEMORY;
4259 c_info->entries = es;
4260 c_info->count = i + 1;
4262 es[i] = talloc(es, struct lsa_ForestTrustCollisionRecord);
4263 if (!es[i]) {
4264 return NT_STATUS_NO_MEMORY;
4267 es[i]->index = idx;
4268 es[i]->type = collision_type;
4269 es[i]->flags.flags = conflict_type;
4270 es[i]->name.string = talloc_strdup(es[i], tdo_name);
4271 if (!es[i]->name.string) {
4272 return NT_STATUS_NO_MEMORY;
4274 es[i]->name.size = strlen(es[i]->name.string);
4276 return NT_STATUS_OK;
4280 lsa_lsaRSetForestTrustInformation
4282 static NTSTATUS dcesrv_lsa_lsaRSetForestTrustInformation(struct dcesrv_call_state *dce_call,
4283 TALLOC_CTX *mem_ctx,
4284 struct lsa_lsaRSetForestTrustInformation *r)
4286 struct dcesrv_handle *h;
4287 struct lsa_policy_state *p_state;
4288 const char *trust_attrs[] = { "trustPartner", "trustAttributes",
4289 "msDS-TrustForestTrustInfo", NULL };
4290 struct ldb_message **dom_res = NULL;
4291 struct ldb_dn *tdo_dn;
4292 struct ldb_message *msg;
4293 int num_res, i;
4294 const char *td_name;
4295 uint32_t trust_attributes;
4296 struct lsa_ForestTrustCollisionInfo *c_info;
4297 struct ForestTrustInfo *nfti;
4298 struct ForestTrustInfo *fti;
4299 DATA_BLOB ft_blob;
4300 enum ndr_err_code ndr_err;
4301 NTSTATUS nt_status;
4302 bool am_rodc;
4303 int ret;
4305 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
4307 p_state = h->data;
4309 if (strcmp(p_state->domain_dns, p_state->forest_dns)) {
4310 return NT_STATUS_INVALID_DOMAIN_STATE;
4313 /* abort if we are not a PDC */
4314 if (!samdb_is_pdc(p_state->sam_ldb)) {
4315 return NT_STATUS_INVALID_DOMAIN_ROLE;
4318 ret = samdb_rodc(p_state->sam_ldb, &am_rodc);
4319 if (ret == LDB_SUCCESS && am_rodc) {
4320 return NT_STATUS_NO_SUCH_DOMAIN;
4323 /* check caller has TRUSTED_SET_AUTH */
4325 /* fetch all trusted domain objects */
4326 num_res = gendb_search(p_state->sam_ldb, mem_ctx,
4327 p_state->system_dn,
4328 &dom_res, trust_attrs,
4329 "(objectclass=trustedDomain)");
4330 if (num_res == 0) {
4331 return NT_STATUS_NO_SUCH_DOMAIN;
4334 for (i = 0; i < num_res; i++) {
4335 td_name = ldb_msg_find_attr_as_string(dom_res[i],
4336 "trustPartner", NULL);
4337 if (!td_name) {
4338 return NT_STATUS_INVALID_DOMAIN_STATE;
4340 if (strcasecmp_m(td_name,
4341 r->in.trusted_domain_name->string) == 0) {
4342 break;
4345 if (i >= num_res) {
4346 return NT_STATUS_NO_SUCH_DOMAIN;
4349 tdo_dn = dom_res[i]->dn;
4351 trust_attributes = ldb_msg_find_attr_as_uint(dom_res[i],
4352 "trustAttributes", 0);
4353 if (!(trust_attributes & NETR_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
4354 return NT_STATUS_INVALID_PARAMETER;
4357 if (r->in.highest_record_type >= LSA_FOREST_TRUST_RECORD_TYPE_LAST) {
4358 return NT_STATUS_INVALID_PARAMETER;
4361 nfti = talloc(mem_ctx, struct ForestTrustInfo);
4362 if (!nfti) {
4363 return NT_STATUS_NO_MEMORY;
4366 nt_status = make_ft_info(nfti, r->in.forest_trust_info, nfti);
4367 if (!NT_STATUS_IS_OK(nt_status)) {
4368 return nt_status;
4371 c_info = talloc_zero(r->out.collision_info,
4372 struct lsa_ForestTrustCollisionInfo);
4373 if (!c_info) {
4374 return NT_STATUS_NO_MEMORY;
4377 /* first check own info, then other domains */
4378 fti = talloc(mem_ctx, struct ForestTrustInfo);
4379 if (!fti) {
4380 return NT_STATUS_NO_MEMORY;
4383 nt_status = own_ft_info(p_state, fti);
4384 if (!NT_STATUS_IS_OK(nt_status)) {
4385 return nt_status;
4388 nt_status = check_ft_info(c_info, p_state->domain_dns,
4389 fti, nfti, c_info);
4390 if (!NT_STATUS_IS_OK(nt_status)) {
4391 return nt_status;
4394 for (i = 0; i < num_res; i++) {
4395 fti = talloc(mem_ctx, struct ForestTrustInfo);
4396 if (!fti) {
4397 return NT_STATUS_NO_MEMORY;
4400 nt_status = get_ft_info(mem_ctx, dom_res[i], fti);
4401 if (!NT_STATUS_IS_OK(nt_status)) {
4402 if (NT_STATUS_EQUAL(nt_status,
4403 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4404 continue;
4406 return nt_status;
4409 td_name = ldb_msg_find_attr_as_string(dom_res[i],
4410 "trustPartner", NULL);
4411 if (!td_name) {
4412 return NT_STATUS_INVALID_DOMAIN_STATE;
4415 nt_status = check_ft_info(c_info, td_name, fti, nfti, c_info);
4416 if (!NT_STATUS_IS_OK(nt_status)) {
4417 return nt_status;
4421 *r->out.collision_info = c_info;
4423 if (r->in.check_only != 0) {
4424 return NT_STATUS_OK;
4427 /* not just a check, write info back */
4429 ndr_err = ndr_push_struct_blob(&ft_blob, mem_ctx, nfti,
4430 (ndr_push_flags_fn_t)ndr_push_ForestTrustInfo);
4431 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
4432 return NT_STATUS_INVALID_PARAMETER;
4435 msg = ldb_msg_new(mem_ctx);
4436 if (msg == NULL) {
4437 return NT_STATUS_NO_MEMORY;
4440 msg->dn = ldb_dn_copy(mem_ctx, tdo_dn);
4441 if (!msg->dn) {
4442 return NT_STATUS_NO_MEMORY;
4445 ret = ldb_msg_add_empty(msg, "msDS-TrustForestTrustInfo",
4446 LDB_FLAG_MOD_REPLACE, NULL);
4447 if (ret != LDB_SUCCESS) {
4448 return NT_STATUS_NO_MEMORY;
4450 ret = ldb_msg_add_value(msg, "msDS-TrustForestTrustInfo",
4451 &ft_blob, NULL);
4452 if (ret != LDB_SUCCESS) {
4453 return NT_STATUS_NO_MEMORY;
4456 ret = ldb_modify(p_state->sam_ldb, msg);
4457 if (ret != LDB_SUCCESS) {
4458 DEBUG(0, ("Failed to store Forest Trust Info: %s\n",
4459 ldb_errstring(p_state->sam_ldb)));
4461 switch (ret) {
4462 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
4463 return NT_STATUS_ACCESS_DENIED;
4464 default:
4465 return NT_STATUS_INTERNAL_DB_CORRUPTION;
4469 return NT_STATUS_OK;
4473 lsa_CREDRRENAME
4475 static NTSTATUS dcesrv_lsa_CREDRRENAME(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4476 struct lsa_CREDRRENAME *r)
4478 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4484 lsa_LSAROPENPOLICYSCE
4486 static NTSTATUS dcesrv_lsa_LSAROPENPOLICYSCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4487 struct lsa_LSAROPENPOLICYSCE *r)
4489 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4494 lsa_LSARADTREGISTERSECURITYEVENTSOURCE
4496 static NTSTATUS dcesrv_lsa_LSARADTREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4497 struct lsa_LSARADTREGISTERSECURITYEVENTSOURCE *r)
4499 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4504 lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE
4506 static NTSTATUS dcesrv_lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4507 struct lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE *r)
4509 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4514 lsa_LSARADTREPORTSECURITYEVENT
4516 static NTSTATUS dcesrv_lsa_LSARADTREPORTSECURITYEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4517 struct lsa_LSARADTREPORTSECURITYEVENT *r)
4519 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4523 /* include the generated boilerplate */
4524 #include "librpc/gen_ndr/ndr_lsa_s.c"
4528 /*****************************************
4529 NOTE! The remaining calls below were
4530 removed in w2k3, so the DCESRV_FAULT()
4531 replies are the correct implementation. Do
4532 not try and fill these in with anything else
4533 ******************************************/
4536 dssetup_DsRoleDnsNameToFlatName
4538 static WERROR dcesrv_dssetup_DsRoleDnsNameToFlatName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4539 struct dssetup_DsRoleDnsNameToFlatName *r)
4541 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4546 dssetup_DsRoleDcAsDc
4548 static WERROR dcesrv_dssetup_DsRoleDcAsDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4549 struct dssetup_DsRoleDcAsDc *r)
4551 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4556 dssetup_DsRoleDcAsReplica
4558 static WERROR dcesrv_dssetup_DsRoleDcAsReplica(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4559 struct dssetup_DsRoleDcAsReplica *r)
4561 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4566 dssetup_DsRoleDemoteDc
4568 static WERROR dcesrv_dssetup_DsRoleDemoteDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4569 struct dssetup_DsRoleDemoteDc *r)
4571 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4576 dssetup_DsRoleGetDcOperationProgress
4578 static WERROR dcesrv_dssetup_DsRoleGetDcOperationProgress(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4579 struct dssetup_DsRoleGetDcOperationProgress *r)
4581 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4586 dssetup_DsRoleGetDcOperationResults
4588 static WERROR dcesrv_dssetup_DsRoleGetDcOperationResults(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4589 struct dssetup_DsRoleGetDcOperationResults *r)
4591 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4596 dssetup_DsRoleCancel
4598 static WERROR dcesrv_dssetup_DsRoleCancel(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4599 struct dssetup_DsRoleCancel *r)
4601 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4606 dssetup_DsRoleServerSaveStateForUpgrade
4608 static WERROR dcesrv_dssetup_DsRoleServerSaveStateForUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4609 struct dssetup_DsRoleServerSaveStateForUpgrade *r)
4611 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4616 dssetup_DsRoleUpgradeDownlevelServer
4618 static WERROR dcesrv_dssetup_DsRoleUpgradeDownlevelServer(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4619 struct dssetup_DsRoleUpgradeDownlevelServer *r)
4621 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4626 dssetup_DsRoleAbortDownlevelServerUpgrade
4628 static WERROR dcesrv_dssetup_DsRoleAbortDownlevelServerUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4629 struct dssetup_DsRoleAbortDownlevelServerUpgrade *r)
4631 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4635 /* include the generated boilerplate */
4636 #include "librpc/gen_ndr/ndr_dssetup_s.c"
4638 NTSTATUS dcerpc_server_lsa_init(void)
4640 NTSTATUS ret;
4642 ret = dcerpc_server_dssetup_init();
4643 if (!NT_STATUS_IS_OK(ret)) {
4644 return ret;
4646 ret = dcerpc_server_lsarpc_init();
4647 if (!NT_STATUS_IS_OK(ret)) {
4648 return ret;
4650 return ret;