gpfs: Move set_gpfs_lease to vfs_gpfs.c
[Samba.git] / source4 / rpc_server / lsa / dcesrv_lsa.c
blob688702b939d1b0ca699d46e4d806e75cb6de41e4
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 if (!NT_STATUS_IS_OK(status)) {
88 TALLOC_FREE(tmp_ctx);
89 return status;
92 domain_admins_sid = dom_sid_add_rid(tmp_ctx, domain_sid, DOMAIN_RID_ADMINS);
93 if (domain_admins_sid == NULL) {
94 TALLOC_FREE(tmp_ctx);
95 return NT_STATUS_NO_MEMORY;
98 domain_admins_sid_str = dom_sid_string(tmp_ctx, domain_admins_sid);
99 if (domain_admins_sid_str == NULL) {
100 TALLOC_FREE(tmp_ctx);
101 return NT_STATUS_NO_MEMORY;
104 sidstr = dom_sid_string(tmp_ctx, sid);
105 if (sidstr == NULL) {
106 TALLOC_FREE(tmp_ctx);
107 return NT_STATUS_NO_MEMORY;
110 *sd = security_descriptor_dacl_create(mem_ctx,
111 0, sidstr, NULL,
113 SID_WORLD,
114 SEC_ACE_TYPE_ACCESS_ALLOWED,
115 SEC_GENERIC_EXECUTE | SEC_GENERIC_READ, 0,
117 SID_BUILTIN_ADMINISTRATORS,
118 SEC_ACE_TYPE_ACCESS_ALLOWED,
119 SEC_GENERIC_ALL, 0,
121 SID_BUILTIN_ACCOUNT_OPERATORS,
122 SEC_ACE_TYPE_ACCESS_ALLOWED,
123 SEC_GENERIC_ALL, 0,
125 domain_admins_sid_str,
126 SEC_ACE_TYPE_ACCESS_ALLOWED,
127 SEC_GENERIC_ALL, 0,
129 sidstr,
130 SEC_ACE_TYPE_ACCESS_ALLOWED,
131 sid_access, 0,
133 NULL);
134 talloc_free(tmp_ctx);
136 NT_STATUS_HAVE_NO_MEMORY(*sd);
138 return NT_STATUS_OK;
142 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call,
143 TALLOC_CTX *mem_ctx,
144 struct lsa_EnumAccountRights *r);
146 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
147 TALLOC_CTX *mem_ctx,
148 struct lsa_policy_state *state,
149 int ldb_flag,
150 struct dom_sid *sid,
151 const struct lsa_RightSet *rights);
154 lsa_Close
156 static NTSTATUS dcesrv_lsa_Close(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
157 struct lsa_Close *r)
159 enum dcerpc_transport_t transport =
160 dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description);
161 struct dcesrv_handle *h;
163 if (transport != NCACN_NP && transport != NCALRPC) {
164 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
167 *r->out.handle = *r->in.handle;
169 DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
171 talloc_free(h);
173 ZERO_STRUCTP(r->out.handle);
175 return NT_STATUS_OK;
180 lsa_Delete
182 static NTSTATUS dcesrv_lsa_Delete(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
183 struct lsa_Delete *r)
185 return NT_STATUS_NOT_SUPPORTED;
190 lsa_DeleteObject
192 static NTSTATUS dcesrv_lsa_DeleteObject(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
193 struct lsa_DeleteObject *r)
195 struct dcesrv_handle *h;
196 int ret;
198 DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
200 if (h->wire_handle.handle_type == LSA_HANDLE_SECRET) {
201 struct lsa_secret_state *secret_state = h->data;
203 /* Ensure user is permitted to delete this... */
204 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
206 case SECURITY_SYSTEM:
207 case SECURITY_ADMINISTRATOR:
208 break;
209 default:
210 /* Users and anonymous are not allowed to delete things */
211 return NT_STATUS_ACCESS_DENIED;
214 ret = ldb_delete(secret_state->sam_ldb,
215 secret_state->secret_dn);
216 if (ret != LDB_SUCCESS) {
217 return NT_STATUS_INVALID_HANDLE;
220 ZERO_STRUCTP(r->out.handle);
222 return NT_STATUS_OK;
224 } else if (h->wire_handle.handle_type == LSA_HANDLE_TRUSTED_DOMAIN) {
225 struct lsa_trusted_domain_state *trusted_domain_state =
226 talloc_get_type(h->data, struct lsa_trusted_domain_state);
227 ret = ldb_transaction_start(trusted_domain_state->policy->sam_ldb);
228 if (ret != LDB_SUCCESS) {
229 return NT_STATUS_INTERNAL_DB_CORRUPTION;
232 ret = ldb_delete(trusted_domain_state->policy->sam_ldb,
233 trusted_domain_state->trusted_domain_dn);
234 if (ret != LDB_SUCCESS) {
235 ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
236 return NT_STATUS_INVALID_HANDLE;
239 if (trusted_domain_state->trusted_domain_user_dn) {
240 ret = ldb_delete(trusted_domain_state->policy->sam_ldb,
241 trusted_domain_state->trusted_domain_user_dn);
242 if (ret != LDB_SUCCESS) {
243 ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
244 return NT_STATUS_INVALID_HANDLE;
248 ret = ldb_transaction_commit(trusted_domain_state->policy->sam_ldb);
249 if (ret != LDB_SUCCESS) {
250 return NT_STATUS_INTERNAL_DB_CORRUPTION;
253 ZERO_STRUCTP(r->out.handle);
255 return NT_STATUS_OK;
257 } else if (h->wire_handle.handle_type == LSA_HANDLE_ACCOUNT) {
258 struct lsa_RightSet *rights;
259 struct lsa_account_state *astate;
260 struct lsa_EnumAccountRights r2;
261 NTSTATUS status;
263 rights = talloc(mem_ctx, struct lsa_RightSet);
265 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
267 astate = h->data;
269 r2.in.handle = &astate->policy->handle->wire_handle;
270 r2.in.sid = astate->account_sid;
271 r2.out.rights = rights;
273 /* dcesrv_lsa_EnumAccountRights takes a LSA_HANDLE_POLICY,
274 but we have a LSA_HANDLE_ACCOUNT here, so this call
275 will always fail */
276 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
277 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
278 return NT_STATUS_OK;
281 if (!NT_STATUS_IS_OK(status)) {
282 return status;
285 status = dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
286 LDB_FLAG_MOD_DELETE, astate->account_sid,
287 r2.out.rights);
288 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
289 return NT_STATUS_OK;
292 if (!NT_STATUS_IS_OK(status)) {
293 return status;
296 ZERO_STRUCTP(r->out.handle);
298 return NT_STATUS_OK;
301 return NT_STATUS_INVALID_HANDLE;
306 lsa_EnumPrivs
308 static NTSTATUS dcesrv_lsa_EnumPrivs(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
309 struct lsa_EnumPrivs *r)
311 struct dcesrv_handle *h;
312 uint32_t i;
313 enum sec_privilege priv;
314 const char *privname;
316 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
318 i = *r->in.resume_handle;
320 while (((priv = sec_privilege_from_index(i)) != SEC_PRIV_INVALID) &&
321 r->out.privs->count < r->in.max_count) {
322 struct lsa_PrivEntry *e;
323 privname = sec_privilege_name(priv);
324 r->out.privs->privs = talloc_realloc(r->out.privs,
325 r->out.privs->privs,
326 struct lsa_PrivEntry,
327 r->out.privs->count+1);
328 if (r->out.privs->privs == NULL) {
329 return NT_STATUS_NO_MEMORY;
331 e = &r->out.privs->privs[r->out.privs->count];
332 e->luid.low = priv;
333 e->luid.high = 0;
334 e->name.string = privname;
335 r->out.privs->count++;
336 i++;
339 *r->out.resume_handle = i;
341 return NT_STATUS_OK;
346 lsa_QuerySecObj
348 static NTSTATUS dcesrv_lsa_QuerySecurity(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
349 struct lsa_QuerySecurity *r)
351 struct dcesrv_handle *h;
352 struct security_descriptor *sd;
353 NTSTATUS status;
354 struct dom_sid *sid;
356 DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
358 sid = &dce_call->conn->auth_state.session_info->security_token->sids[PRIMARY_USER_SID_INDEX];
360 if (h->wire_handle.handle_type == LSA_HANDLE_POLICY) {
361 status = dcesrv_build_lsa_sd(mem_ctx, &sd, sid, 0);
362 } else if (h->wire_handle.handle_type == LSA_HANDLE_ACCOUNT) {
363 status = dcesrv_build_lsa_sd(mem_ctx, &sd, sid,
364 LSA_ACCOUNT_ALL_ACCESS);
365 } else {
366 return NT_STATUS_INVALID_HANDLE;
368 NT_STATUS_NOT_OK_RETURN(status);
370 (*r->out.sdbuf) = talloc(mem_ctx, struct sec_desc_buf);
371 NT_STATUS_HAVE_NO_MEMORY(*r->out.sdbuf);
373 (*r->out.sdbuf)->sd = sd;
375 return NT_STATUS_OK;
380 lsa_SetSecObj
382 static NTSTATUS dcesrv_lsa_SetSecObj(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
383 struct lsa_SetSecObj *r)
385 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
390 lsa_ChangePassword
392 static NTSTATUS dcesrv_lsa_ChangePassword(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
393 struct lsa_ChangePassword *r)
395 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
399 dssetup_DsRoleGetPrimaryDomainInformation
401 This is not an LSA call, but is the only call left on the DSSETUP
402 pipe (after the pipe was truncated), and needs lsa_get_policy_state
404 static WERROR dcesrv_dssetup_DsRoleGetPrimaryDomainInformation(struct dcesrv_call_state *dce_call,
405 TALLOC_CTX *mem_ctx,
406 struct dssetup_DsRoleGetPrimaryDomainInformation *r)
408 union dssetup_DsRoleInfo *info;
410 info = talloc_zero(mem_ctx, union dssetup_DsRoleInfo);
411 W_ERROR_HAVE_NO_MEMORY(info);
413 switch (r->in.level) {
414 case DS_ROLE_BASIC_INFORMATION:
416 enum dssetup_DsRole role = DS_ROLE_STANDALONE_SERVER;
417 uint32_t flags = 0;
418 const char *domain = NULL;
419 const char *dns_domain = NULL;
420 const char *forest = NULL;
421 struct GUID domain_guid;
422 struct lsa_policy_state *state;
424 NTSTATUS status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx, &state);
425 if (!NT_STATUS_IS_OK(status)) {
426 return ntstatus_to_werror(status);
429 ZERO_STRUCT(domain_guid);
431 switch (lpcfg_server_role(dce_call->conn->dce_ctx->lp_ctx)) {
432 case ROLE_STANDALONE:
433 role = DS_ROLE_STANDALONE_SERVER;
434 break;
435 case ROLE_DOMAIN_MEMBER:
436 role = DS_ROLE_MEMBER_SERVER;
437 break;
438 case ROLE_ACTIVE_DIRECTORY_DC:
439 if (samdb_is_pdc(state->sam_ldb)) {
440 role = DS_ROLE_PRIMARY_DC;
441 } else {
442 role = DS_ROLE_BACKUP_DC;
444 break;
447 switch (lpcfg_server_role(dce_call->conn->dce_ctx->lp_ctx)) {
448 case ROLE_STANDALONE:
449 domain = talloc_strdup(mem_ctx, lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx));
450 W_ERROR_HAVE_NO_MEMORY(domain);
451 break;
452 case ROLE_DOMAIN_MEMBER:
453 domain = talloc_strdup(mem_ctx, lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx));
454 W_ERROR_HAVE_NO_MEMORY(domain);
455 /* TODO: what is with dns_domain and forest and guid? */
456 break;
457 case ROLE_ACTIVE_DIRECTORY_DC:
458 flags = DS_ROLE_PRIMARY_DS_RUNNING;
460 if (state->mixed_domain == 1) {
461 flags |= DS_ROLE_PRIMARY_DS_MIXED_MODE;
464 domain = state->domain_name;
465 dns_domain = state->domain_dns;
466 forest = state->forest_dns;
468 domain_guid = state->domain_guid;
469 flags |= DS_ROLE_PRIMARY_DOMAIN_GUID_PRESENT;
470 break;
473 info->basic.role = role;
474 info->basic.flags = flags;
475 info->basic.domain = domain;
476 info->basic.dns_domain = dns_domain;
477 info->basic.forest = forest;
478 info->basic.domain_guid = domain_guid;
480 r->out.info = info;
481 return WERR_OK;
483 case DS_ROLE_UPGRADE_STATUS:
485 info->upgrade.upgrading = DS_ROLE_NOT_UPGRADING;
486 info->upgrade.previous_role = DS_ROLE_PREVIOUS_UNKNOWN;
488 r->out.info = info;
489 return WERR_OK;
491 case DS_ROLE_OP_STATUS:
493 info->opstatus.status = DS_ROLE_OP_IDLE;
495 r->out.info = info;
496 return WERR_OK;
498 default:
499 return WERR_INVALID_PARAM;
504 fill in the AccountDomain info
506 static NTSTATUS dcesrv_lsa_info_AccountDomain(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
507 struct lsa_DomainInfo *info)
509 info->name.string = state->domain_name;
510 info->sid = state->domain_sid;
512 return NT_STATUS_OK;
516 fill in the DNS domain info
518 static NTSTATUS dcesrv_lsa_info_DNS(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
519 struct lsa_DnsDomainInfo *info)
521 info->name.string = state->domain_name;
522 info->sid = state->domain_sid;
523 info->dns_domain.string = state->domain_dns;
524 info->dns_forest.string = state->forest_dns;
525 info->domain_guid = state->domain_guid;
527 return NT_STATUS_OK;
531 lsa_QueryInfoPolicy2
533 static NTSTATUS dcesrv_lsa_QueryInfoPolicy2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
534 struct lsa_QueryInfoPolicy2 *r)
536 struct lsa_policy_state *state;
537 struct dcesrv_handle *h;
538 union lsa_PolicyInformation *info;
540 *r->out.info = NULL;
542 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
544 state = h->data;
546 info = talloc_zero(mem_ctx, union lsa_PolicyInformation);
547 if (!info) {
548 return NT_STATUS_NO_MEMORY;
550 *r->out.info = info;
552 switch (r->in.level) {
553 case LSA_POLICY_INFO_AUDIT_LOG:
554 /* we don't need to fill in any of this */
555 ZERO_STRUCT(info->audit_log);
556 return NT_STATUS_OK;
557 case LSA_POLICY_INFO_AUDIT_EVENTS:
558 /* we don't need to fill in any of this */
559 ZERO_STRUCT(info->audit_events);
560 return NT_STATUS_OK;
561 case LSA_POLICY_INFO_PD:
562 /* we don't need to fill in any of this */
563 ZERO_STRUCT(info->pd);
564 return NT_STATUS_OK;
566 case LSA_POLICY_INFO_DOMAIN:
567 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->domain);
568 case LSA_POLICY_INFO_ACCOUNT_DOMAIN:
569 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->account_domain);
570 case LSA_POLICY_INFO_L_ACCOUNT_DOMAIN:
571 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->l_account_domain);
573 case LSA_POLICY_INFO_ROLE:
574 info->role.role = LSA_ROLE_PRIMARY;
575 return NT_STATUS_OK;
577 case LSA_POLICY_INFO_DNS:
578 case LSA_POLICY_INFO_DNS_INT:
579 return dcesrv_lsa_info_DNS(state, mem_ctx, &info->dns);
581 case LSA_POLICY_INFO_REPLICA:
582 ZERO_STRUCT(info->replica);
583 return NT_STATUS_OK;
585 case LSA_POLICY_INFO_QUOTA:
586 ZERO_STRUCT(info->quota);
587 return NT_STATUS_OK;
589 case LSA_POLICY_INFO_MOD:
590 case LSA_POLICY_INFO_AUDIT_FULL_SET:
591 case LSA_POLICY_INFO_AUDIT_FULL_QUERY:
592 /* windows gives INVALID_PARAMETER */
593 *r->out.info = NULL;
594 return NT_STATUS_INVALID_PARAMETER;
597 *r->out.info = NULL;
598 return NT_STATUS_INVALID_INFO_CLASS;
602 lsa_QueryInfoPolicy
604 static NTSTATUS dcesrv_lsa_QueryInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
605 struct lsa_QueryInfoPolicy *r)
607 struct lsa_QueryInfoPolicy2 r2;
608 NTSTATUS status;
610 ZERO_STRUCT(r2);
612 r2.in.handle = r->in.handle;
613 r2.in.level = r->in.level;
614 r2.out.info = r->out.info;
616 status = dcesrv_lsa_QueryInfoPolicy2(dce_call, mem_ctx, &r2);
618 return status;
622 lsa_SetInfoPolicy
624 static NTSTATUS dcesrv_lsa_SetInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
625 struct lsa_SetInfoPolicy *r)
627 /* need to support this */
628 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
633 lsa_ClearAuditLog
635 static NTSTATUS dcesrv_lsa_ClearAuditLog(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
636 struct lsa_ClearAuditLog *r)
638 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
643 lsa_CreateAccount
645 This call does not seem to have any long-term effects, hence no database operations
647 we need to talk to the MS product group to find out what this account database means!
649 answer is that the lsa database is totally separate from the SAM and
650 ldap databases. We are going to need a separate ldb to store these
651 accounts. The SIDs on this account bear no relation to the SIDs in
654 static NTSTATUS dcesrv_lsa_CreateAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
655 struct lsa_CreateAccount *r)
657 struct lsa_account_state *astate;
659 struct lsa_policy_state *state;
660 struct dcesrv_handle *h, *ah;
662 ZERO_STRUCTP(r->out.acct_handle);
664 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
666 state = h->data;
668 astate = talloc(dce_call->conn, struct lsa_account_state);
669 if (astate == NULL) {
670 return NT_STATUS_NO_MEMORY;
673 astate->account_sid = dom_sid_dup(astate, r->in.sid);
674 if (astate->account_sid == NULL) {
675 talloc_free(astate);
676 return NT_STATUS_NO_MEMORY;
679 astate->policy = talloc_reference(astate, state);
680 astate->access_mask = r->in.access_mask;
682 ah = dcesrv_handle_new(dce_call->context, LSA_HANDLE_ACCOUNT);
683 if (!ah) {
684 talloc_free(astate);
685 return NT_STATUS_NO_MEMORY;
688 ah->data = talloc_steal(ah, astate);
690 *r->out.acct_handle = ah->wire_handle;
692 return NT_STATUS_OK;
697 lsa_EnumAccounts
699 static NTSTATUS dcesrv_lsa_EnumAccounts(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
700 struct lsa_EnumAccounts *r)
702 struct dcesrv_handle *h;
703 struct lsa_policy_state *state;
704 int ret;
705 struct ldb_message **res;
706 const char * const attrs[] = { "objectSid", NULL};
707 uint32_t count, i;
709 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
711 state = h->data;
713 /* NOTE: This call must only return accounts that have at least
714 one privilege set
716 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
717 "(&(objectSid=*)(privilege=*))");
718 if (ret < 0) {
719 return NT_STATUS_INTERNAL_DB_CORRUPTION;
722 if (*r->in.resume_handle >= ret) {
723 return NT_STATUS_NO_MORE_ENTRIES;
726 count = ret - *r->in.resume_handle;
727 if (count > r->in.num_entries) {
728 count = r->in.num_entries;
731 if (count == 0) {
732 return NT_STATUS_NO_MORE_ENTRIES;
735 r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, count);
736 if (r->out.sids->sids == NULL) {
737 return NT_STATUS_NO_MEMORY;
740 for (i=0;i<count;i++) {
741 r->out.sids->sids[i].sid =
742 samdb_result_dom_sid(r->out.sids->sids,
743 res[i + *r->in.resume_handle],
744 "objectSid");
745 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
748 r->out.sids->num_sids = count;
749 *r->out.resume_handle = count + *r->in.resume_handle;
751 return NT_STATUS_OK;
754 /* This decrypts and returns Trusted Domain Auth Information Internal data */
755 static NTSTATUS get_trustdom_auth_blob(struct dcesrv_call_state *dce_call,
756 TALLOC_CTX *mem_ctx, DATA_BLOB *auth_blob,
757 struct trustDomainPasswords *auth_struct)
759 DATA_BLOB session_key = data_blob(NULL, 0);
760 enum ndr_err_code ndr_err;
761 NTSTATUS nt_status;
763 nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
764 if (!NT_STATUS_IS_OK(nt_status)) {
765 return nt_status;
768 arcfour_crypt_blob(auth_blob->data, auth_blob->length, &session_key);
769 ndr_err = ndr_pull_struct_blob(auth_blob, mem_ctx,
770 auth_struct,
771 (ndr_pull_flags_fn_t)ndr_pull_trustDomainPasswords);
772 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
773 return NT_STATUS_INVALID_PARAMETER;
776 return NT_STATUS_OK;
779 static NTSTATUS get_trustauth_inout_blob(struct dcesrv_call_state *dce_call,
780 TALLOC_CTX *mem_ctx,
781 struct trustAuthInOutBlob *iopw,
782 DATA_BLOB *trustauth_blob)
784 enum ndr_err_code ndr_err;
786 ndr_err = ndr_push_struct_blob(trustauth_blob, mem_ctx,
787 iopw,
788 (ndr_push_flags_fn_t)ndr_push_trustAuthInOutBlob);
789 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
790 return NT_STATUS_INVALID_PARAMETER;
793 return NT_STATUS_OK;
796 static NTSTATUS add_trust_user(TALLOC_CTX *mem_ctx,
797 struct ldb_context *sam_ldb,
798 struct ldb_dn *base_dn,
799 const char *netbios_name,
800 struct trustAuthInOutBlob *in,
801 struct ldb_dn **user_dn)
803 struct ldb_request *req;
804 struct ldb_message *msg;
805 struct ldb_dn *dn;
806 uint32_t i;
807 int ret;
809 dn = ldb_dn_copy(mem_ctx, base_dn);
810 if (!dn) {
811 return NT_STATUS_NO_MEMORY;
813 if (!ldb_dn_add_child_fmt(dn, "cn=%s$,cn=users", netbios_name)) {
814 return NT_STATUS_NO_MEMORY;
817 msg = ldb_msg_new(mem_ctx);
818 if (!msg) {
819 return NT_STATUS_NO_MEMORY;
821 msg->dn = dn;
823 ret = ldb_msg_add_string(msg, "objectClass", "user");
824 if (ret != LDB_SUCCESS) {
825 return NT_STATUS_NO_MEMORY;
828 ret = ldb_msg_add_fmt(msg, "samAccountName", "%s$", netbios_name);
829 if (ret != LDB_SUCCESS) {
830 return NT_STATUS_NO_MEMORY;
833 ret = samdb_msg_add_uint(sam_ldb, msg, msg, "userAccountControl",
834 UF_INTERDOMAIN_TRUST_ACCOUNT);
835 if (ret != LDB_SUCCESS) {
836 return NT_STATUS_NO_MEMORY;
839 for (i = 0; i < in->count; i++) {
840 const char *attribute;
841 struct ldb_val v;
842 switch (in->current.array[i].AuthType) {
843 case TRUST_AUTH_TYPE_NT4OWF:
844 attribute = "unicodePwd";
845 v.data = (uint8_t *)&in->current.array[i].AuthInfo.nt4owf.password;
846 v.length = 16;
847 break;
848 case TRUST_AUTH_TYPE_CLEAR:
849 attribute = "clearTextPassword";
850 v.data = in->current.array[i].AuthInfo.clear.password;
851 v.length = in->current.array[i].AuthInfo.clear.size;
852 break;
853 default:
854 continue;
857 ret = ldb_msg_add_value(msg, attribute, &v, NULL);
858 if (ret != LDB_SUCCESS) {
859 return NT_STATUS_NO_MEMORY;
863 /* create the trusted_domain user account */
864 ret = ldb_build_add_req(&req, sam_ldb, mem_ctx, msg, NULL, NULL,
865 ldb_op_default_callback, NULL);
866 if (ret != LDB_SUCCESS) {
867 return NT_STATUS_NO_MEMORY;
870 ret = ldb_request_add_control(req, DSDB_CONTROL_PERMIT_INTERDOMAIN_TRUST_UAC_OID,
871 false, NULL);
872 if (ret != LDB_SUCCESS) {
873 return NT_STATUS_NO_MEMORY;
876 ret = dsdb_autotransaction_request(sam_ldb, req);
877 if (ret != LDB_SUCCESS) {
878 DEBUG(0,("Failed to create user record %s: %s\n",
879 ldb_dn_get_linearized(msg->dn),
880 ldb_errstring(sam_ldb)));
882 switch (ret) {
883 case LDB_ERR_ENTRY_ALREADY_EXISTS:
884 return NT_STATUS_DOMAIN_EXISTS;
885 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
886 return NT_STATUS_ACCESS_DENIED;
887 default:
888 return NT_STATUS_INTERNAL_DB_CORRUPTION;
892 if (user_dn) {
893 *user_dn = dn;
895 return NT_STATUS_OK;
899 lsa_CreateTrustedDomainEx2
901 static NTSTATUS dcesrv_lsa_CreateTrustedDomain_base(struct dcesrv_call_state *dce_call,
902 TALLOC_CTX *mem_ctx,
903 struct lsa_CreateTrustedDomainEx2 *r,
904 int op,
905 struct lsa_TrustDomainInfoAuthInfo *unencrypted_auth_info)
907 struct dcesrv_handle *policy_handle;
908 struct lsa_policy_state *policy_state;
909 struct lsa_trusted_domain_state *trusted_domain_state;
910 struct dcesrv_handle *handle;
911 struct ldb_message **msgs, *msg;
912 const char *attrs[] = {
913 NULL
915 const char *netbios_name;
916 const char *dns_name;
917 const char *name;
918 DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
919 struct trustDomainPasswords auth_struct;
920 int ret;
921 NTSTATUS nt_status;
922 struct ldb_context *sam_ldb;
924 DCESRV_PULL_HANDLE(policy_handle, r->in.policy_handle, LSA_HANDLE_POLICY);
925 ZERO_STRUCTP(r->out.trustdom_handle);
927 policy_state = policy_handle->data;
928 sam_ldb = policy_state->sam_ldb;
930 netbios_name = r->in.info->netbios_name.string;
931 if (!netbios_name) {
932 return NT_STATUS_INVALID_PARAMETER;
935 dns_name = r->in.info->domain_name.string;
937 trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
938 if (!trusted_domain_state) {
939 return NT_STATUS_NO_MEMORY;
941 trusted_domain_state->policy = policy_state;
943 if (strcasecmp(netbios_name, "BUILTIN") == 0
944 || (dns_name && strcasecmp(dns_name, "BUILTIN") == 0)
945 || (dom_sid_in_domain(policy_state->builtin_sid, r->in.info->sid))) {
946 return NT_STATUS_INVALID_PARAMETER;
949 if (strcasecmp(netbios_name, policy_state->domain_name) == 0
950 || strcasecmp(netbios_name, policy_state->domain_dns) == 0
951 || (dns_name && strcasecmp(dns_name, policy_state->domain_dns) == 0)
952 || (dns_name && strcasecmp(dns_name, policy_state->domain_name) == 0)
953 || (dom_sid_equal(policy_state->domain_sid, r->in.info->sid))) {
954 return NT_STATUS_CURRENT_DOMAIN_NOT_ALLOWED;
957 /* While this is a REF pointer, some of the functions that wrap this don't provide this */
958 if (op == NDR_LSA_CREATETRUSTEDDOMAIN) {
959 /* No secrets are created at this time, for this function */
960 auth_struct.outgoing.count = 0;
961 auth_struct.incoming.count = 0;
962 } else if (op == NDR_LSA_CREATETRUSTEDDOMAINEX2) {
963 auth_blob = data_blob_const(r->in.auth_info_internal->auth_blob.data,
964 r->in.auth_info_internal->auth_blob.size);
965 nt_status = get_trustdom_auth_blob(dce_call, mem_ctx,
966 &auth_blob, &auth_struct);
967 if (!NT_STATUS_IS_OK(nt_status)) {
968 return nt_status;
970 } else if (op == NDR_LSA_CREATETRUSTEDDOMAINEX) {
972 if (unencrypted_auth_info->incoming_count > 1) {
973 return NT_STATUS_INVALID_PARAMETER;
976 /* more investigation required here, do not create secrets for
977 * now */
978 auth_struct.outgoing.count = 0;
979 auth_struct.incoming.count = 0;
980 } else {
981 return NT_STATUS_INVALID_PARAMETER;
984 if (auth_struct.incoming.count) {
985 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
986 &auth_struct.incoming,
987 &trustAuthIncoming);
988 if (!NT_STATUS_IS_OK(nt_status)) {
989 return nt_status;
991 } else {
992 trustAuthIncoming = data_blob(NULL, 0);
995 if (auth_struct.outgoing.count) {
996 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
997 &auth_struct.outgoing,
998 &trustAuthOutgoing);
999 if (!NT_STATUS_IS_OK(nt_status)) {
1000 return nt_status;
1002 } else {
1003 trustAuthOutgoing = data_blob(NULL, 0);
1006 ret = ldb_transaction_start(sam_ldb);
1007 if (ret != LDB_SUCCESS) {
1008 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1011 if (dns_name) {
1012 char *dns_encoded = ldb_binary_encode_string(mem_ctx, dns_name);
1013 char *netbios_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
1014 /* search for the trusted_domain record */
1015 ret = gendb_search(sam_ldb,
1016 mem_ctx, policy_state->system_dn, &msgs, attrs,
1017 "(&(|(flatname=%s)(cn=%s)(trustPartner=%s)(flatname=%s)(cn=%s)(trustPartner=%s))(objectclass=trustedDomain))",
1018 dns_encoded, dns_encoded, dns_encoded, netbios_encoded, netbios_encoded, netbios_encoded);
1019 if (ret > 0) {
1020 ldb_transaction_cancel(sam_ldb);
1021 return NT_STATUS_OBJECT_NAME_COLLISION;
1023 } else {
1024 char *netbios_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
1025 /* search for the trusted_domain record */
1026 ret = gendb_search(sam_ldb,
1027 mem_ctx, policy_state->system_dn, &msgs, attrs,
1028 "(&(|(flatname=%s)(cn=%s)(trustPartner=%s))(objectclass=trustedDomain))",
1029 netbios_encoded, netbios_encoded, netbios_encoded);
1030 if (ret > 0) {
1031 ldb_transaction_cancel(sam_ldb);
1032 return NT_STATUS_OBJECT_NAME_COLLISION;
1036 if (ret < 0 ) {
1037 ldb_transaction_cancel(sam_ldb);
1038 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1041 name = dns_name ? dns_name : netbios_name;
1043 msg = ldb_msg_new(mem_ctx);
1044 if (msg == NULL) {
1045 return NT_STATUS_NO_MEMORY;
1048 msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
1049 if ( ! ldb_dn_add_child_fmt(msg->dn, "cn=%s", name)) {
1050 ldb_transaction_cancel(sam_ldb);
1051 return NT_STATUS_NO_MEMORY;
1054 ldb_msg_add_string(msg, "flatname", netbios_name);
1056 if (r->in.info->sid) {
1057 ret = samdb_msg_add_dom_sid(sam_ldb, mem_ctx, msg, "securityIdentifier", r->in.info->sid);
1058 if (ret != LDB_SUCCESS) {
1059 ldb_transaction_cancel(sam_ldb);
1060 return NT_STATUS_INVALID_PARAMETER;
1064 ldb_msg_add_string(msg, "objectClass", "trustedDomain");
1066 samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustType", r->in.info->trust_type);
1068 samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustAttributes", r->in.info->trust_attributes);
1070 samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustDirection", r->in.info->trust_direction);
1072 if (dns_name) {
1073 ldb_msg_add_string(msg, "trustPartner", dns_name);
1076 if (trustAuthIncoming.data) {
1077 ret = ldb_msg_add_value(msg, "trustAuthIncoming", &trustAuthIncoming, NULL);
1078 if (ret != LDB_SUCCESS) {
1079 ldb_transaction_cancel(sam_ldb);
1080 return NT_STATUS_NO_MEMORY;
1083 if (trustAuthOutgoing.data) {
1084 ret = ldb_msg_add_value(msg, "trustAuthOutgoing", &trustAuthOutgoing, NULL);
1085 if (ret != LDB_SUCCESS) {
1086 ldb_transaction_cancel(sam_ldb);
1087 return NT_STATUS_NO_MEMORY;
1091 trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msg->dn);
1093 /* create the trusted_domain */
1094 ret = ldb_add(sam_ldb, msg);
1095 switch (ret) {
1096 case LDB_SUCCESS:
1097 break;
1098 case LDB_ERR_ENTRY_ALREADY_EXISTS:
1099 ldb_transaction_cancel(sam_ldb);
1100 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1101 ldb_dn_get_linearized(msg->dn),
1102 ldb_errstring(sam_ldb)));
1103 return NT_STATUS_DOMAIN_EXISTS;
1104 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1105 ldb_transaction_cancel(sam_ldb);
1106 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1107 ldb_dn_get_linearized(msg->dn),
1108 ldb_errstring(sam_ldb)));
1109 return NT_STATUS_ACCESS_DENIED;
1110 default:
1111 ldb_transaction_cancel(sam_ldb);
1112 DEBUG(0,("Failed to create user record %s: %s\n",
1113 ldb_dn_get_linearized(msg->dn),
1114 ldb_errstring(sam_ldb)));
1115 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1118 if (r->in.info->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
1119 struct ldb_dn *user_dn;
1120 /* Inbound trusts must also create a cn=users object to match */
1121 nt_status = add_trust_user(mem_ctx, sam_ldb,
1122 policy_state->domain_dn,
1123 netbios_name,
1124 &auth_struct.incoming,
1125 &user_dn);
1126 if (!NT_STATUS_IS_OK(nt_status)) {
1127 ldb_transaction_cancel(sam_ldb);
1128 return nt_status;
1131 /* save the trust user dn */
1132 trusted_domain_state->trusted_domain_user_dn
1133 = talloc_steal(trusted_domain_state, user_dn);
1136 ret = ldb_transaction_commit(sam_ldb);
1137 if (ret != LDB_SUCCESS) {
1138 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1141 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1142 if (!handle) {
1143 return NT_STATUS_NO_MEMORY;
1146 handle->data = talloc_steal(handle, trusted_domain_state);
1148 trusted_domain_state->access_mask = r->in.access_mask;
1149 trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
1151 *r->out.trustdom_handle = handle->wire_handle;
1153 return NT_STATUS_OK;
1157 lsa_CreateTrustedDomainEx2
1159 static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx2(struct dcesrv_call_state *dce_call,
1160 TALLOC_CTX *mem_ctx,
1161 struct lsa_CreateTrustedDomainEx2 *r)
1163 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, r, NDR_LSA_CREATETRUSTEDDOMAINEX2, NULL);
1166 lsa_CreateTrustedDomainEx
1168 static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx(struct dcesrv_call_state *dce_call,
1169 TALLOC_CTX *mem_ctx,
1170 struct lsa_CreateTrustedDomainEx *r)
1172 struct lsa_CreateTrustedDomainEx2 r2;
1174 r2.in.policy_handle = r->in.policy_handle;
1175 r2.in.info = r->in.info;
1176 r2.out.trustdom_handle = r->out.trustdom_handle;
1177 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAINEX, r->in.auth_info);
1181 lsa_CreateTrustedDomain
1183 static NTSTATUS dcesrv_lsa_CreateTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1184 struct lsa_CreateTrustedDomain *r)
1186 struct lsa_CreateTrustedDomainEx2 r2;
1188 r2.in.policy_handle = r->in.policy_handle;
1189 r2.in.info = talloc(mem_ctx, struct lsa_TrustDomainInfoInfoEx);
1190 if (!r2.in.info) {
1191 return NT_STATUS_NO_MEMORY;
1194 r2.in.info->domain_name.string = NULL;
1195 r2.in.info->netbios_name = r->in.info->name;
1196 r2.in.info->sid = r->in.info->sid;
1197 r2.in.info->trust_direction = LSA_TRUST_DIRECTION_OUTBOUND;
1198 r2.in.info->trust_type = LSA_TRUST_TYPE_DOWNLEVEL;
1199 r2.in.info->trust_attributes = 0;
1201 r2.in.access_mask = r->in.access_mask;
1202 r2.out.trustdom_handle = r->out.trustdom_handle;
1204 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAIN, NULL);
1207 static NTSTATUS dcesrv_lsa_OpenTrustedDomain_common(
1208 struct dcesrv_call_state *dce_call,
1209 TALLOC_CTX *tmp_mem,
1210 struct lsa_policy_state *policy_state,
1211 const char *filter,
1212 uint32_t access_mask,
1213 struct dcesrv_handle **_handle)
1215 struct lsa_trusted_domain_state *trusted_domain_state;
1216 struct dcesrv_handle *handle;
1217 struct ldb_message **msgs;
1218 const char *attrs[] = {
1219 "trustDirection",
1220 "flatname",
1221 NULL
1223 uint32_t direction;
1224 int ret;
1226 /* TODO: perform access checks */
1228 /* search for the trusted_domain record */
1229 ret = gendb_search(policy_state->sam_ldb, tmp_mem,
1230 policy_state->system_dn,
1231 &msgs, attrs, "%s", filter);
1232 if (ret == 0) {
1233 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1236 if (ret != 1) {
1237 DEBUG(0,("Found %d records matching %s under %s\n", ret,
1238 filter,
1239 ldb_dn_get_linearized(policy_state->system_dn)));
1240 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1243 trusted_domain_state = talloc_zero(tmp_mem,
1244 struct lsa_trusted_domain_state);
1245 if (!trusted_domain_state) {
1246 return NT_STATUS_NO_MEMORY;
1248 trusted_domain_state->policy = policy_state;
1250 trusted_domain_state->trusted_domain_dn =
1251 talloc_steal(trusted_domain_state, msgs[0]->dn);
1253 direction = ldb_msg_find_attr_as_int(msgs[0], "trustDirection", 0);
1254 if (direction & LSA_TRUST_DIRECTION_INBOUND) {
1255 const char *flatname = ldb_msg_find_attr_as_string(msgs[0],
1256 "flatname", NULL);
1258 /* search for the trusted_domain account */
1259 ret = gendb_search(policy_state->sam_ldb, tmp_mem,
1260 policy_state->domain_dn,
1261 &msgs, attrs,
1262 "(&(samaccountname=%s$)(objectclass=user)"
1263 "(userAccountControl:%s:=%u))",
1264 flatname,
1265 LDB_OID_COMPARATOR_AND,
1266 UF_INTERDOMAIN_TRUST_ACCOUNT);
1267 if (ret == 1) {
1268 trusted_domain_state->trusted_domain_user_dn =
1269 talloc_steal(trusted_domain_state, msgs[0]->dn);
1273 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1274 if (!handle) {
1275 return NT_STATUS_NO_MEMORY;
1278 handle->data = talloc_steal(handle, trusted_domain_state);
1280 trusted_domain_state->access_mask = access_mask;
1281 trusted_domain_state->policy = talloc_reference(trusted_domain_state,
1282 policy_state);
1284 *_handle = handle;
1286 return NT_STATUS_OK;
1290 lsa_OpenTrustedDomain
1292 static NTSTATUS dcesrv_lsa_OpenTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1293 struct lsa_OpenTrustedDomain *r)
1295 struct dcesrv_handle *policy_handle;
1296 struct lsa_policy_state *policy_state;
1297 struct dcesrv_handle *handle;
1298 const char *sid_string;
1299 char *filter;
1300 NTSTATUS status;
1302 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1303 ZERO_STRUCTP(r->out.trustdom_handle);
1304 policy_state = policy_handle->data;
1306 sid_string = dom_sid_string(mem_ctx, r->in.sid);
1307 if (!sid_string) {
1308 return NT_STATUS_NO_MEMORY;
1311 filter = talloc_asprintf(mem_ctx,
1312 "(&(securityIdentifier=%s)"
1313 "(objectclass=trustedDomain))",
1314 sid_string);
1315 if (filter == NULL) {
1316 return NT_STATUS_NO_MEMORY;
1319 status = dcesrv_lsa_OpenTrustedDomain_common(dce_call, mem_ctx,
1320 policy_state,
1321 filter,
1322 r->in.access_mask,
1323 &handle);
1324 if (!NT_STATUS_IS_OK(status)) {
1325 return status;
1328 *r->out.trustdom_handle = handle->wire_handle;
1330 return NT_STATUS_OK;
1335 lsa_OpenTrustedDomainByName
1337 static NTSTATUS dcesrv_lsa_OpenTrustedDomainByName(struct dcesrv_call_state *dce_call,
1338 TALLOC_CTX *mem_ctx,
1339 struct lsa_OpenTrustedDomainByName *r)
1341 struct dcesrv_handle *policy_handle;
1342 struct lsa_policy_state *policy_state;
1343 struct dcesrv_handle *handle;
1344 char *td_name;
1345 char *filter;
1346 NTSTATUS status;
1348 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1349 ZERO_STRUCTP(r->out.trustdom_handle);
1350 policy_state = policy_handle->data;
1352 if (!r->in.name.string) {
1353 return NT_STATUS_INVALID_PARAMETER;
1356 /* search for the trusted_domain record */
1357 td_name = ldb_binary_encode_string(mem_ctx, r->in.name.string);
1358 if (td_name == NULL) {
1359 return NT_STATUS_NO_MEMORY;
1362 filter = talloc_asprintf(mem_ctx,
1363 "(&(|(flatname=%s)(cn=%s)(trustPartner=%s))"
1364 "(objectclass=trustedDomain))",
1365 td_name, td_name, td_name);
1366 if (filter == NULL) {
1367 return NT_STATUS_NO_MEMORY;
1370 status = dcesrv_lsa_OpenTrustedDomain_common(dce_call, mem_ctx,
1371 policy_state,
1372 filter,
1373 r->in.access_mask,
1374 &handle);
1375 if (!NT_STATUS_IS_OK(status)) {
1376 return status;
1379 *r->out.trustdom_handle = handle->wire_handle;
1381 return NT_STATUS_OK;
1387 lsa_SetTrustedDomainInfo
1389 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1390 struct lsa_SetTrustedDomainInfo *r)
1392 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1397 /* parameters 4 to 6 are optional if the dn is a dn of a TDO object,
1398 * otherwise at least one must be provided */
1399 static NTSTATUS get_tdo(struct ldb_context *sam, TALLOC_CTX *mem_ctx,
1400 struct ldb_dn *basedn, const char *dns_domain,
1401 const char *netbios, struct dom_sid2 *sid,
1402 struct ldb_message ***msgs)
1404 const char *attrs[] = { "flatname", "trustPartner",
1405 "securityIdentifier", "trustDirection",
1406 "trustType", "trustAttributes",
1407 "trustPosixOffset",
1408 "msDs-supportedEncryptionTypes",
1409 "msDS-TrustForestTrustInfo",
1410 NULL
1412 char *dns = NULL;
1413 char *nbn = NULL;
1414 char *sidstr = NULL;
1415 char *filter;
1416 int ret;
1419 if (dns_domain || netbios || sid) {
1420 filter = talloc_strdup(mem_ctx,
1421 "(&(objectclass=trustedDomain)(|");
1422 } else {
1423 filter = talloc_strdup(mem_ctx,
1424 "(objectclass=trustedDomain)");
1426 if (!filter) {
1427 return NT_STATUS_NO_MEMORY;
1430 if (dns_domain) {
1431 dns = ldb_binary_encode_string(mem_ctx, dns_domain);
1432 if (!dns) {
1433 return NT_STATUS_NO_MEMORY;
1435 filter = talloc_asprintf_append(filter,
1436 "(trustPartner=%s)", dns);
1437 if (!filter) {
1438 return NT_STATUS_NO_MEMORY;
1441 if (netbios) {
1442 nbn = ldb_binary_encode_string(mem_ctx, netbios);
1443 if (!nbn) {
1444 return NT_STATUS_NO_MEMORY;
1446 filter = talloc_asprintf_append(filter,
1447 "(flatname=%s)", nbn);
1448 if (!filter) {
1449 return NT_STATUS_NO_MEMORY;
1452 if (sid) {
1453 sidstr = dom_sid_string(mem_ctx, sid);
1454 if (!sidstr) {
1455 return NT_STATUS_INVALID_PARAMETER;
1457 filter = talloc_asprintf_append(filter,
1458 "(securityIdentifier=%s)",
1459 sidstr);
1460 if (!filter) {
1461 return NT_STATUS_NO_MEMORY;
1464 if (dns_domain || netbios || sid) {
1465 filter = talloc_asprintf_append(filter, "))");
1466 if (!filter) {
1467 return NT_STATUS_NO_MEMORY;
1471 ret = gendb_search(sam, mem_ctx, basedn, msgs, attrs, "%s", filter);
1472 if (ret == 0) {
1473 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1476 if (ret != 1) {
1477 return NT_STATUS_OBJECT_NAME_COLLISION;
1480 return NT_STATUS_OK;
1483 static NTSTATUS update_uint32_t_value(TALLOC_CTX *mem_ctx,
1484 struct ldb_context *sam_ldb,
1485 struct ldb_message *orig,
1486 struct ldb_message *dest,
1487 const char *attribute,
1488 uint32_t value,
1489 uint32_t *orig_value)
1491 const struct ldb_val *orig_val;
1492 uint32_t orig_uint = 0;
1493 unsigned int flags = 0;
1494 int ret;
1496 orig_val = ldb_msg_find_ldb_val(orig, attribute);
1497 if (!orig_val || !orig_val->data) {
1498 /* add new attribute */
1499 flags = LDB_FLAG_MOD_ADD;
1501 } else {
1502 errno = 0;
1503 orig_uint = strtoul((const char *)orig_val->data, NULL, 0);
1504 if (errno != 0 || orig_uint != value) {
1505 /* replace also if can't get value */
1506 flags = LDB_FLAG_MOD_REPLACE;
1510 if (flags == 0) {
1511 /* stored value is identical, nothing to change */
1512 goto done;
1515 ret = ldb_msg_add_empty(dest, attribute, flags, NULL);
1516 if (ret != LDB_SUCCESS) {
1517 return NT_STATUS_NO_MEMORY;
1520 ret = samdb_msg_add_uint(sam_ldb, dest, dest, attribute, value);
1521 if (ret != LDB_SUCCESS) {
1522 return NT_STATUS_NO_MEMORY;
1525 done:
1526 if (orig_value) {
1527 *orig_value = orig_uint;
1529 return NT_STATUS_OK;
1532 static NTSTATUS update_trust_user(TALLOC_CTX *mem_ctx,
1533 struct ldb_context *sam_ldb,
1534 struct ldb_dn *base_dn,
1535 bool delete_user,
1536 const char *netbios_name,
1537 struct trustAuthInOutBlob *in)
1539 const char *attrs[] = { "userAccountControl", NULL };
1540 struct ldb_message **msgs;
1541 struct ldb_message *msg;
1542 uint32_t uac;
1543 uint32_t i;
1544 int ret;
1546 ret = gendb_search(sam_ldb, mem_ctx,
1547 base_dn, &msgs, attrs,
1548 "samAccountName=%s$", netbios_name);
1549 if (ret > 1) {
1550 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1553 if (ret == 0) {
1554 if (delete_user) {
1555 return NT_STATUS_OK;
1558 /* ok no existing user, add it from scratch */
1559 return add_trust_user(mem_ctx, sam_ldb, base_dn,
1560 netbios_name, in, NULL);
1563 /* check user is what we are looking for */
1564 uac = ldb_msg_find_attr_as_uint(msgs[0],
1565 "userAccountControl", 0);
1566 if (!(uac & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
1567 return NT_STATUS_OBJECT_NAME_COLLISION;
1570 if (delete_user) {
1571 ret = ldb_delete(sam_ldb, msgs[0]->dn);
1572 switch (ret) {
1573 case LDB_SUCCESS:
1574 return NT_STATUS_OK;
1575 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1576 return NT_STATUS_ACCESS_DENIED;
1577 default:
1578 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1582 /* entry exists, just modify secret if any */
1583 if (in == NULL || in->count == 0) {
1584 return NT_STATUS_OK;
1587 msg = ldb_msg_new(mem_ctx);
1588 if (!msg) {
1589 return NT_STATUS_NO_MEMORY;
1591 msg->dn = msgs[0]->dn;
1593 for (i = 0; i < in->count; i++) {
1594 const char *attribute;
1595 struct ldb_val v;
1596 switch (in->current.array[i].AuthType) {
1597 case TRUST_AUTH_TYPE_NT4OWF:
1598 attribute = "unicodePwd";
1599 v.data = (uint8_t *)&in->current.array[i].AuthInfo.nt4owf.password;
1600 v.length = 16;
1601 break;
1602 case TRUST_AUTH_TYPE_CLEAR:
1603 attribute = "clearTextPassword";
1604 v.data = in->current.array[i].AuthInfo.clear.password;
1605 v.length = in->current.array[i].AuthInfo.clear.size;
1606 break;
1607 default:
1608 continue;
1611 ret = ldb_msg_add_empty(msg, attribute,
1612 LDB_FLAG_MOD_REPLACE, NULL);
1613 if (ret != LDB_SUCCESS) {
1614 return NT_STATUS_NO_MEMORY;
1617 ret = ldb_msg_add_value(msg, attribute, &v, NULL);
1618 if (ret != LDB_SUCCESS) {
1619 return NT_STATUS_NO_MEMORY;
1623 /* create the trusted_domain user account */
1624 ret = ldb_modify(sam_ldb, msg);
1625 if (ret != LDB_SUCCESS) {
1626 DEBUG(0,("Failed to create user record %s: %s\n",
1627 ldb_dn_get_linearized(msg->dn),
1628 ldb_errstring(sam_ldb)));
1630 switch (ret) {
1631 case LDB_ERR_ENTRY_ALREADY_EXISTS:
1632 return NT_STATUS_DOMAIN_EXISTS;
1633 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1634 return NT_STATUS_ACCESS_DENIED;
1635 default:
1636 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1640 return NT_STATUS_OK;
1644 static NTSTATUS setInfoTrustedDomain_base(struct dcesrv_call_state *dce_call,
1645 struct lsa_policy_state *p_state,
1646 TALLOC_CTX *mem_ctx,
1647 struct ldb_message *dom_msg,
1648 enum lsa_TrustDomInfoEnum level,
1649 union lsa_TrustedDomainInfo *info)
1651 uint32_t *posix_offset = NULL;
1652 struct lsa_TrustDomainInfoInfoEx *info_ex = NULL;
1653 struct lsa_TrustDomainInfoAuthInfo *auth_info = NULL;
1654 struct lsa_TrustDomainInfoAuthInfoInternal *auth_info_int = NULL;
1655 uint32_t *enc_types = NULL;
1656 DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
1657 struct trustDomainPasswords auth_struct;
1658 struct trustAuthInOutBlob *current_passwords = NULL;
1659 NTSTATUS nt_status;
1660 struct ldb_message **msgs;
1661 struct ldb_message *msg;
1662 bool add_outgoing = false;
1663 bool add_incoming = false;
1664 bool del_outgoing = false;
1665 bool del_incoming = false;
1666 bool del_forest_info = false;
1667 bool in_transaction = false;
1668 int ret;
1669 bool am_rodc;
1671 switch (level) {
1672 case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
1673 posix_offset = &info->posix_offset.posix_offset;
1674 break;
1675 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
1676 info_ex = &info->info_ex;
1677 break;
1678 case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO:
1679 auth_info = &info->auth_info;
1680 break;
1681 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
1682 posix_offset = &info->full_info.posix_offset.posix_offset;
1683 info_ex = &info->full_info.info_ex;
1684 auth_info = &info->full_info.auth_info;
1685 break;
1686 case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO_INTERNAL:
1687 auth_info_int = &info->auth_info_internal;
1688 break;
1689 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_INTERNAL:
1690 posix_offset = &info->full_info_internal.posix_offset.posix_offset;
1691 info_ex = &info->full_info_internal.info_ex;
1692 auth_info_int = &info->full_info_internal.auth_info;
1693 break;
1694 case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
1695 enc_types = &info->enc_types.enc_types;
1696 break;
1697 default:
1698 return NT_STATUS_INVALID_PARAMETER;
1701 if (auth_info) {
1702 nt_status = auth_info_2_auth_blob(mem_ctx, auth_info,
1703 &trustAuthIncoming,
1704 &trustAuthOutgoing);
1705 if (!NT_STATUS_IS_OK(nt_status)) {
1706 return nt_status;
1708 if (trustAuthIncoming.data) {
1709 /* This does the decode of some of this twice, but it is easier that way */
1710 nt_status = auth_info_2_trustauth_inout(mem_ctx,
1711 auth_info->incoming_count,
1712 auth_info->incoming_current_auth_info,
1713 NULL,
1714 &current_passwords);
1715 if (!NT_STATUS_IS_OK(nt_status)) {
1716 return nt_status;
1721 /* decode auth_info_int if set */
1722 if (auth_info_int) {
1724 /* now decrypt blob */
1725 auth_blob = data_blob_const(auth_info_int->auth_blob.data,
1726 auth_info_int->auth_blob.size);
1728 nt_status = get_trustdom_auth_blob(dce_call, mem_ctx,
1729 &auth_blob, &auth_struct);
1730 if (!NT_STATUS_IS_OK(nt_status)) {
1731 return nt_status;
1735 if (info_ex) {
1736 /* verify data matches */
1737 if (info_ex->trust_attributes &
1738 LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
1739 /* TODO: check what behavior level we have */
1740 if (strcasecmp_m(p_state->domain_dns,
1741 p_state->forest_dns) != 0) {
1742 return NT_STATUS_INVALID_DOMAIN_STATE;
1746 ret = samdb_rodc(p_state->sam_ldb, &am_rodc);
1747 if (ret == LDB_SUCCESS && am_rodc) {
1748 return NT_STATUS_NO_SUCH_DOMAIN;
1751 /* verify only one object matches the dns/netbios/sid
1752 * triplet and that this is the one we already have */
1753 nt_status = get_tdo(p_state->sam_ldb, mem_ctx,
1754 p_state->system_dn,
1755 info_ex->domain_name.string,
1756 info_ex->netbios_name.string,
1757 info_ex->sid, &msgs);
1758 if (!NT_STATUS_IS_OK(nt_status)) {
1759 return nt_status;
1761 if (ldb_dn_compare(dom_msg->dn, msgs[0]->dn) != 0) {
1762 return NT_STATUS_OBJECT_NAME_COLLISION;
1764 talloc_free(msgs);
1767 /* TODO: should we fetch previous values from the existing entry
1768 * and append them ? */
1769 if (auth_info_int && auth_struct.incoming.count) {
1770 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1771 &auth_struct.incoming,
1772 &trustAuthIncoming);
1773 if (!NT_STATUS_IS_OK(nt_status)) {
1774 return nt_status;
1777 current_passwords = &auth_struct.incoming;
1779 } else {
1780 trustAuthIncoming = data_blob(NULL, 0);
1783 if (auth_info_int && auth_struct.outgoing.count) {
1784 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1785 &auth_struct.outgoing,
1786 &trustAuthOutgoing);
1787 if (!NT_STATUS_IS_OK(nt_status)) {
1788 return nt_status;
1790 } else {
1791 trustAuthOutgoing = data_blob(NULL, 0);
1794 msg = ldb_msg_new(mem_ctx);
1795 if (msg == NULL) {
1796 return NT_STATUS_NO_MEMORY;
1798 msg->dn = dom_msg->dn;
1800 if (posix_offset) {
1801 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1802 dom_msg, msg,
1803 "trustPosixOffset",
1804 *posix_offset, NULL);
1805 if (!NT_STATUS_IS_OK(nt_status)) {
1806 return nt_status;
1810 if (info_ex) {
1811 uint32_t origattrs;
1812 uint32_t changed_attrs;
1813 uint32_t origdir;
1814 int origtype;
1816 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1817 dom_msg, msg,
1818 "trustDirection",
1819 info_ex->trust_direction,
1820 &origdir);
1821 if (!NT_STATUS_IS_OK(nt_status)) {
1822 return nt_status;
1825 if (info_ex->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
1826 if (auth_info != NULL && trustAuthIncoming.length > 0) {
1827 add_incoming = true;
1830 if (info_ex->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND) {
1831 if (auth_info != NULL && trustAuthOutgoing.length > 0) {
1832 add_outgoing = true;
1836 if ((origdir & LSA_TRUST_DIRECTION_INBOUND) &&
1837 !(info_ex->trust_direction & LSA_TRUST_DIRECTION_INBOUND)) {
1838 del_incoming = true;
1840 if ((origdir & LSA_TRUST_DIRECTION_OUTBOUND) &&
1841 !(info_ex->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND)) {
1842 del_outgoing = true;
1845 origtype = ldb_msg_find_attr_as_int(dom_msg, "trustType", -1);
1846 if (origtype == -1 || origtype != info_ex->trust_type) {
1847 DEBUG(1, ("Attempted to change trust type! "
1848 "Operation not handled\n"));
1849 return NT_STATUS_INVALID_PARAMETER;
1852 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1853 dom_msg, msg,
1854 "trustAttributes",
1855 info_ex->trust_attributes,
1856 &origattrs);
1857 if (!NT_STATUS_IS_OK(nt_status)) {
1858 return nt_status;
1860 /* TODO: check forestFunctionality from ldb opaque */
1861 /* TODO: check what is set makes sense */
1863 changed_attrs = origattrs ^ info_ex->trust_attributes;
1864 if (changed_attrs & ~LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
1866 * For now we only allow
1867 * LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE to be changed.
1869 * TODO: we may need to support more attribute changes
1871 DEBUG(1, ("Attempted to change trust attributes "
1872 "(0x%08x != 0x%08x)! "
1873 "Operation not handled yet...\n",
1874 (unsigned)origattrs,
1875 (unsigned)info_ex->trust_attributes));
1876 return NT_STATUS_INVALID_PARAMETER;
1879 if (!(info_ex->trust_attributes &
1880 LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE))
1882 struct ldb_message_element *orig_forest_el = NULL;
1884 orig_forest_el = ldb_msg_find_element(dom_msg,
1885 "msDS-TrustForestTrustInfo");
1886 if (orig_forest_el != NULL) {
1887 del_forest_info = true;
1892 if (enc_types) {
1893 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1894 dom_msg, msg,
1895 "msDS-SupportedEncryptionTypes",
1896 *enc_types, NULL);
1897 if (!NT_STATUS_IS_OK(nt_status)) {
1898 return nt_status;
1902 if (add_incoming || del_incoming) {
1903 ret = ldb_msg_add_empty(msg, "trustAuthIncoming",
1904 LDB_FLAG_MOD_REPLACE, NULL);
1905 if (ret != LDB_SUCCESS) {
1906 return NT_STATUS_NO_MEMORY;
1908 if (add_incoming) {
1909 ret = ldb_msg_add_value(msg, "trustAuthIncoming",
1910 &trustAuthIncoming, NULL);
1911 if (ret != LDB_SUCCESS) {
1912 return NT_STATUS_NO_MEMORY;
1916 if (add_outgoing || del_outgoing) {
1917 ret = ldb_msg_add_empty(msg, "trustAuthOutgoing",
1918 LDB_FLAG_MOD_REPLACE, NULL);
1919 if (ret != LDB_SUCCESS) {
1920 return NT_STATUS_NO_MEMORY;
1922 if (add_outgoing) {
1923 ret = ldb_msg_add_value(msg, "trustAuthOutgoing",
1924 &trustAuthOutgoing, NULL);
1925 if (ret != LDB_SUCCESS) {
1926 return NT_STATUS_NO_MEMORY;
1930 if (del_forest_info) {
1931 ret = ldb_msg_add_empty(msg, "msDS-TrustForestTrustInfo",
1932 LDB_FLAG_MOD_REPLACE, NULL);
1933 if (ret != LDB_SUCCESS) {
1934 return NT_STATUS_NO_MEMORY;
1938 /* start transaction */
1939 ret = ldb_transaction_start(p_state->sam_ldb);
1940 if (ret != LDB_SUCCESS) {
1941 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1943 in_transaction = true;
1945 if (msg->num_elements) {
1946 ret = ldb_modify(p_state->sam_ldb, msg);
1947 if (ret != LDB_SUCCESS) {
1948 DEBUG(1,("Failed to modify trusted domain record %s: %s\n",
1949 ldb_dn_get_linearized(msg->dn),
1950 ldb_errstring(p_state->sam_ldb)));
1951 nt_status = dsdb_ldb_err_to_ntstatus(ret);
1952 goto done;
1956 if (add_incoming || del_incoming) {
1957 const char *netbios_name;
1959 netbios_name = ldb_msg_find_attr_as_string(dom_msg,
1960 "flatname", NULL);
1961 if (!netbios_name) {
1962 nt_status = NT_STATUS_INVALID_DOMAIN_STATE;
1963 goto done;
1966 /* We use trustAuthIncoming.data to incidate that auth_struct.incoming is valid */
1967 nt_status = update_trust_user(mem_ctx,
1968 p_state->sam_ldb,
1969 p_state->domain_dn,
1970 del_incoming,
1971 netbios_name,
1972 current_passwords);
1973 if (!NT_STATUS_IS_OK(nt_status)) {
1974 goto done;
1978 /* ok, all fine, commit transaction and return */
1979 ret = ldb_transaction_commit(p_state->sam_ldb);
1980 if (ret != LDB_SUCCESS) {
1981 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1983 in_transaction = false;
1985 nt_status = NT_STATUS_OK;
1987 done:
1988 if (in_transaction) {
1989 ldb_transaction_cancel(p_state->sam_ldb);
1991 return nt_status;
1995 lsa_SetInfomrationTrustedDomain
1997 static NTSTATUS dcesrv_lsa_SetInformationTrustedDomain(
1998 struct dcesrv_call_state *dce_call,
1999 TALLOC_CTX *mem_ctx,
2000 struct lsa_SetInformationTrustedDomain *r)
2002 struct dcesrv_handle *h;
2003 struct lsa_trusted_domain_state *td_state;
2004 struct ldb_message **msgs;
2005 NTSTATUS nt_status;
2007 DCESRV_PULL_HANDLE(h, r->in.trustdom_handle,
2008 LSA_HANDLE_TRUSTED_DOMAIN);
2010 td_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
2012 /* get the trusted domain object */
2013 nt_status = get_tdo(td_state->policy->sam_ldb, mem_ctx,
2014 td_state->trusted_domain_dn,
2015 NULL, NULL, NULL, &msgs);
2016 if (!NT_STATUS_IS_OK(nt_status)) {
2017 if (NT_STATUS_EQUAL(nt_status,
2018 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2019 return nt_status;
2021 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2024 return setInfoTrustedDomain_base(dce_call, td_state->policy, mem_ctx,
2025 msgs[0], r->in.level, r->in.info);
2030 lsa_DeleteTrustedDomain
2032 static NTSTATUS dcesrv_lsa_DeleteTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2033 struct lsa_DeleteTrustedDomain *r)
2035 NTSTATUS status;
2036 struct lsa_OpenTrustedDomain opn;
2037 struct lsa_DeleteObject del;
2038 struct dcesrv_handle *h;
2040 opn.in.handle = r->in.handle;
2041 opn.in.sid = r->in.dom_sid;
2042 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2043 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2044 if (!opn.out.trustdom_handle) {
2045 return NT_STATUS_NO_MEMORY;
2047 status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
2048 if (!NT_STATUS_IS_OK(status)) {
2049 return status;
2052 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2053 talloc_steal(mem_ctx, h);
2055 del.in.handle = opn.out.trustdom_handle;
2056 del.out.handle = opn.out.trustdom_handle;
2057 status = dcesrv_lsa_DeleteObject(dce_call, mem_ctx, &del);
2058 if (!NT_STATUS_IS_OK(status)) {
2059 return status;
2061 return NT_STATUS_OK;
2064 static NTSTATUS fill_trust_domain_ex(TALLOC_CTX *mem_ctx,
2065 struct ldb_message *msg,
2066 struct lsa_TrustDomainInfoInfoEx *info_ex)
2068 info_ex->domain_name.string
2069 = ldb_msg_find_attr_as_string(msg, "trustPartner", NULL);
2070 info_ex->netbios_name.string
2071 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2072 info_ex->sid
2073 = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
2074 info_ex->trust_direction
2075 = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
2076 info_ex->trust_type
2077 = ldb_msg_find_attr_as_int(msg, "trustType", 0);
2078 info_ex->trust_attributes
2079 = ldb_msg_find_attr_as_int(msg, "trustAttributes", 0);
2080 return NT_STATUS_OK;
2084 lsa_QueryTrustedDomainInfo
2086 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2087 struct lsa_QueryTrustedDomainInfo *r)
2089 union lsa_TrustedDomainInfo *info = NULL;
2090 struct dcesrv_handle *h;
2091 struct lsa_trusted_domain_state *trusted_domain_state;
2092 struct ldb_message *msg;
2093 int ret;
2094 struct ldb_message **res;
2095 const char *attrs[] = {
2096 "flatname",
2097 "trustPartner",
2098 "securityIdentifier",
2099 "trustDirection",
2100 "trustType",
2101 "trustAttributes",
2102 "msDs-supportedEncryptionTypes",
2103 NULL
2106 DCESRV_PULL_HANDLE(h, r->in.trustdom_handle, LSA_HANDLE_TRUSTED_DOMAIN);
2108 trusted_domain_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
2110 /* pull all the user attributes */
2111 ret = gendb_search_dn(trusted_domain_state->policy->sam_ldb, mem_ctx,
2112 trusted_domain_state->trusted_domain_dn, &res, attrs);
2113 if (ret != 1) {
2114 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2116 msg = res[0];
2118 info = talloc_zero(mem_ctx, union lsa_TrustedDomainInfo);
2119 if (!info) {
2120 return NT_STATUS_NO_MEMORY;
2122 *r->out.info = info;
2124 switch (r->in.level) {
2125 case LSA_TRUSTED_DOMAIN_INFO_NAME:
2126 info->name.netbios_name.string
2127 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2128 break;
2129 case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
2130 info->posix_offset.posix_offset
2131 = ldb_msg_find_attr_as_uint(msg, "posixOffset", 0);
2132 break;
2133 #if 0 /* Win2k3 doesn't implement this */
2134 case LSA_TRUSTED_DOMAIN_INFO_BASIC:
2135 r->out.info->info_basic.netbios_name.string
2136 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2137 r->out.info->info_basic.sid
2138 = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
2139 break;
2140 #endif
2141 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
2142 return fill_trust_domain_ex(mem_ctx, msg, &info->info_ex);
2144 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
2145 ZERO_STRUCT(info->full_info);
2146 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info.info_ex);
2147 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_2_INTERNAL:
2148 ZERO_STRUCT(info->full_info2_internal);
2149 info->full_info2_internal.posix_offset.posix_offset
2150 = ldb_msg_find_attr_as_uint(msg, "posixOffset", 0);
2151 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info2_internal.info.info_ex);
2153 case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
2154 info->enc_types.enc_types
2155 = ldb_msg_find_attr_as_uint(msg, "msDs-supportedEncryptionTypes", KERB_ENCTYPE_RC4_HMAC_MD5);
2156 break;
2158 case LSA_TRUSTED_DOMAIN_INFO_CONTROLLERS:
2159 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX2_INTERNAL:
2160 /* oops, we don't want to return the info after all */
2161 talloc_free(info);
2162 *r->out.info = NULL;
2163 return NT_STATUS_INVALID_PARAMETER;
2164 default:
2165 /* oops, we don't want to return the info after all */
2166 talloc_free(info);
2167 *r->out.info = NULL;
2168 return NT_STATUS_INVALID_INFO_CLASS;
2171 return NT_STATUS_OK;
2176 lsa_QueryTrustedDomainInfoBySid
2178 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoBySid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2179 struct lsa_QueryTrustedDomainInfoBySid *r)
2181 NTSTATUS status;
2182 struct lsa_OpenTrustedDomain opn;
2183 struct lsa_QueryTrustedDomainInfo query;
2184 struct dcesrv_handle *h;
2186 opn.in.handle = r->in.handle;
2187 opn.in.sid = r->in.dom_sid;
2188 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2189 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2190 if (!opn.out.trustdom_handle) {
2191 return NT_STATUS_NO_MEMORY;
2193 status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
2194 if (!NT_STATUS_IS_OK(status)) {
2195 return status;
2198 /* Ensure this handle goes away at the end of this call */
2199 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2200 talloc_steal(mem_ctx, h);
2202 query.in.trustdom_handle = opn.out.trustdom_handle;
2203 query.in.level = r->in.level;
2204 query.out.info = r->out.info;
2205 status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2206 if (!NT_STATUS_IS_OK(status)) {
2207 return status;
2210 return NT_STATUS_OK;
2214 lsa_SetTrustedDomainInfoByName
2216 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2217 TALLOC_CTX *mem_ctx,
2218 struct lsa_SetTrustedDomainInfoByName *r)
2220 struct dcesrv_handle *policy_handle;
2221 struct lsa_policy_state *policy_state;
2222 struct ldb_message **msgs;
2223 NTSTATUS nt_status;
2225 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2226 policy_state = policy_handle->data;
2228 /* get the trusted domain object */
2229 nt_status = get_tdo(policy_state->sam_ldb, mem_ctx,
2230 policy_state->domain_dn,
2231 r->in.trusted_domain->string,
2232 r->in.trusted_domain->string,
2233 NULL, &msgs);
2234 if (!NT_STATUS_IS_OK(nt_status)) {
2235 if (NT_STATUS_EQUAL(nt_status,
2236 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2237 return nt_status;
2239 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2242 return setInfoTrustedDomain_base(dce_call, policy_state, mem_ctx,
2243 msgs[0], r->in.level, r->in.info);
2247 lsa_QueryTrustedDomainInfoByName
2249 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2250 TALLOC_CTX *mem_ctx,
2251 struct lsa_QueryTrustedDomainInfoByName *r)
2253 NTSTATUS status;
2254 struct lsa_OpenTrustedDomainByName opn;
2255 struct lsa_QueryTrustedDomainInfo query;
2256 struct dcesrv_handle *h;
2258 opn.in.handle = r->in.handle;
2259 opn.in.name = *r->in.trusted_domain;
2260 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2261 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2262 if (!opn.out.trustdom_handle) {
2263 return NT_STATUS_NO_MEMORY;
2265 status = dcesrv_lsa_OpenTrustedDomainByName(dce_call, mem_ctx, &opn);
2266 if (!NT_STATUS_IS_OK(status)) {
2267 return status;
2270 /* Ensure this handle goes away at the end of this call */
2271 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2272 talloc_steal(mem_ctx, h);
2274 query.in.trustdom_handle = opn.out.trustdom_handle;
2275 query.in.level = r->in.level;
2276 query.out.info = r->out.info;
2277 status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2278 if (!NT_STATUS_IS_OK(status)) {
2279 return status;
2282 return NT_STATUS_OK;
2286 lsa_CloseTrustedDomainEx
2288 static NTSTATUS dcesrv_lsa_CloseTrustedDomainEx(struct dcesrv_call_state *dce_call,
2289 TALLOC_CTX *mem_ctx,
2290 struct lsa_CloseTrustedDomainEx *r)
2292 /* The result of a bad hair day from an IDL programmer? Not
2293 * implmented in Win2k3. You should always just lsa_Close
2294 * anyway. */
2295 return NT_STATUS_NOT_IMPLEMENTED;
2300 comparison function for sorting lsa_DomainInformation array
2302 static int compare_DomainInfo(struct lsa_DomainInfo *e1, struct lsa_DomainInfo *e2)
2304 return strcasecmp_m(e1->name.string, e2->name.string);
2308 lsa_EnumTrustDom
2310 static NTSTATUS dcesrv_lsa_EnumTrustDom(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2311 struct lsa_EnumTrustDom *r)
2313 struct dcesrv_handle *policy_handle;
2314 struct lsa_DomainInfo *entries;
2315 struct lsa_policy_state *policy_state;
2316 struct ldb_message **domains;
2317 const char *attrs[] = {
2318 "flatname",
2319 "securityIdentifier",
2320 NULL
2324 int count, i;
2326 *r->out.resume_handle = 0;
2328 r->out.domains->domains = NULL;
2329 r->out.domains->count = 0;
2331 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2333 policy_state = policy_handle->data;
2335 /* search for all users in this domain. This could possibly be cached and
2336 resumed based on resume_key */
2337 count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
2338 "objectclass=trustedDomain");
2339 if (count < 0) {
2340 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2343 /* convert to lsa_TrustInformation format */
2344 entries = talloc_array(mem_ctx, struct lsa_DomainInfo, count);
2345 if (!entries) {
2346 return NT_STATUS_NO_MEMORY;
2348 for (i=0;i<count;i++) {
2349 entries[i].sid = samdb_result_dom_sid(mem_ctx, domains[i], "securityIdentifier");
2350 entries[i].name.string = ldb_msg_find_attr_as_string(domains[i], "flatname", NULL);
2353 /* sort the results by name */
2354 TYPESAFE_QSORT(entries, count, compare_DomainInfo);
2356 if (*r->in.resume_handle >= count) {
2357 *r->out.resume_handle = -1;
2359 return NT_STATUS_NO_MORE_ENTRIES;
2362 /* return the rest, limit by max_size. Note that we
2363 use the w2k3 element size value of 60 */
2364 r->out.domains->count = count - *r->in.resume_handle;
2365 r->out.domains->count = MIN(r->out.domains->count,
2366 1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_MULTIPLIER));
2368 r->out.domains->domains = entries + *r->in.resume_handle;
2369 r->out.domains->count = r->out.domains->count;
2371 if (r->out.domains->count < count - *r->in.resume_handle) {
2372 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2373 return STATUS_MORE_ENTRIES;
2376 /* according to MS-LSAD 3.1.4.7.8 output resume handle MUST
2377 * always be larger than the previous input resume handle, in
2378 * particular when hitting the last query it is vital to set the
2379 * resume handle correctly to avoid infinite client loops, as
2380 * seen e.g. with Windows XP SP3 when resume handle is 0 and
2381 * status is NT_STATUS_OK - gd */
2383 *r->out.resume_handle = (uint32_t)-1;
2385 return NT_STATUS_OK;
2389 comparison function for sorting lsa_DomainInformation array
2391 static int compare_TrustDomainInfoInfoEx(struct lsa_TrustDomainInfoInfoEx *e1, struct lsa_TrustDomainInfoInfoEx *e2)
2393 return strcasecmp_m(e1->netbios_name.string, e2->netbios_name.string);
2397 lsa_EnumTrustedDomainsEx
2399 static NTSTATUS dcesrv_lsa_EnumTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2400 struct lsa_EnumTrustedDomainsEx *r)
2402 struct dcesrv_handle *policy_handle;
2403 struct lsa_TrustDomainInfoInfoEx *entries;
2404 struct lsa_policy_state *policy_state;
2405 struct ldb_message **domains;
2406 const char *attrs[] = {
2407 "flatname",
2408 "trustPartner",
2409 "securityIdentifier",
2410 "trustDirection",
2411 "trustType",
2412 "trustAttributes",
2413 NULL
2415 NTSTATUS nt_status;
2417 int count, i;
2419 *r->out.resume_handle = 0;
2421 r->out.domains->domains = NULL;
2422 r->out.domains->count = 0;
2424 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2426 policy_state = policy_handle->data;
2428 /* search for all users in this domain. This could possibly be cached and
2429 resumed based on resume_key */
2430 count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
2431 "objectclass=trustedDomain");
2432 if (count < 0) {
2433 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2436 /* convert to lsa_DomainInformation format */
2437 entries = talloc_array(mem_ctx, struct lsa_TrustDomainInfoInfoEx, count);
2438 if (!entries) {
2439 return NT_STATUS_NO_MEMORY;
2441 for (i=0;i<count;i++) {
2442 nt_status = fill_trust_domain_ex(mem_ctx, domains[i], &entries[i]);
2443 if (!NT_STATUS_IS_OK(nt_status)) {
2444 return nt_status;
2448 /* sort the results by name */
2449 TYPESAFE_QSORT(entries, count, compare_TrustDomainInfoInfoEx);
2451 if (*r->in.resume_handle >= count) {
2452 *r->out.resume_handle = -1;
2454 return NT_STATUS_NO_MORE_ENTRIES;
2457 /* return the rest, limit by max_size. Note that we
2458 use the w2k3 element size value of 60 */
2459 r->out.domains->count = count - *r->in.resume_handle;
2460 r->out.domains->count = MIN(r->out.domains->count,
2461 1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_EX_MULTIPLIER));
2463 r->out.domains->domains = entries + *r->in.resume_handle;
2464 r->out.domains->count = r->out.domains->count;
2466 if (r->out.domains->count < count - *r->in.resume_handle) {
2467 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2468 return STATUS_MORE_ENTRIES;
2471 return NT_STATUS_OK;
2476 lsa_OpenAccount
2478 static NTSTATUS dcesrv_lsa_OpenAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2479 struct lsa_OpenAccount *r)
2481 struct dcesrv_handle *h, *ah;
2482 struct lsa_policy_state *state;
2483 struct lsa_account_state *astate;
2485 ZERO_STRUCTP(r->out.acct_handle);
2487 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2489 state = h->data;
2491 astate = talloc(dce_call->conn, struct lsa_account_state);
2492 if (astate == NULL) {
2493 return NT_STATUS_NO_MEMORY;
2496 astate->account_sid = dom_sid_dup(astate, r->in.sid);
2497 if (astate->account_sid == NULL) {
2498 talloc_free(astate);
2499 return NT_STATUS_NO_MEMORY;
2502 astate->policy = talloc_reference(astate, state);
2503 astate->access_mask = r->in.access_mask;
2505 ah = dcesrv_handle_new(dce_call->context, LSA_HANDLE_ACCOUNT);
2506 if (!ah) {
2507 talloc_free(astate);
2508 return NT_STATUS_NO_MEMORY;
2511 ah->data = talloc_steal(ah, astate);
2513 *r->out.acct_handle = ah->wire_handle;
2515 return NT_STATUS_OK;
2520 lsa_EnumPrivsAccount
2522 static NTSTATUS dcesrv_lsa_EnumPrivsAccount(struct dcesrv_call_state *dce_call,
2523 TALLOC_CTX *mem_ctx,
2524 struct lsa_EnumPrivsAccount *r)
2526 struct dcesrv_handle *h;
2527 struct lsa_account_state *astate;
2528 int ret;
2529 unsigned int i, j;
2530 struct ldb_message **res;
2531 const char * const attrs[] = { "privilege", NULL};
2532 struct ldb_message_element *el;
2533 const char *sidstr;
2534 struct lsa_PrivilegeSet *privs;
2536 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2538 astate = h->data;
2540 privs = talloc(mem_ctx, struct lsa_PrivilegeSet);
2541 if (privs == NULL) {
2542 return NT_STATUS_NO_MEMORY;
2544 privs->count = 0;
2545 privs->unknown = 0;
2546 privs->set = NULL;
2548 *r->out.privs = privs;
2550 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
2551 if (sidstr == NULL) {
2552 return NT_STATUS_NO_MEMORY;
2555 ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs,
2556 "objectSid=%s", sidstr);
2557 if (ret < 0) {
2558 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2560 if (ret != 1) {
2561 return NT_STATUS_OK;
2564 el = ldb_msg_find_element(res[0], "privilege");
2565 if (el == NULL || el->num_values == 0) {
2566 return NT_STATUS_OK;
2569 privs->set = talloc_array(privs,
2570 struct lsa_LUIDAttribute, el->num_values);
2571 if (privs->set == NULL) {
2572 return NT_STATUS_NO_MEMORY;
2575 j = 0;
2576 for (i=0;i<el->num_values;i++) {
2577 int id = sec_privilege_id((const char *)el->values[i].data);
2578 if (id == SEC_PRIV_INVALID) {
2579 /* Perhaps an account right, not a privilege */
2580 continue;
2582 privs->set[j].attribute = 0;
2583 privs->set[j].luid.low = id;
2584 privs->set[j].luid.high = 0;
2585 j++;
2588 privs->count = j;
2590 return NT_STATUS_OK;
2594 lsa_EnumAccountRights
2596 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call,
2597 TALLOC_CTX *mem_ctx,
2598 struct lsa_EnumAccountRights *r)
2600 struct dcesrv_handle *h;
2601 struct lsa_policy_state *state;
2602 int ret;
2603 unsigned int i;
2604 struct ldb_message **res;
2605 const char * const attrs[] = { "privilege", NULL};
2606 const char *sidstr;
2607 struct ldb_message_element *el;
2609 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2611 state = h->data;
2613 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, r->in.sid);
2614 if (sidstr == NULL) {
2615 return NT_STATUS_NO_MEMORY;
2618 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
2619 "(&(objectSid=%s)(privilege=*))", sidstr);
2620 if (ret == 0) {
2621 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2623 if (ret != 1) {
2624 DEBUG(3, ("searching for account rights for SID: %s failed: %s",
2625 dom_sid_string(mem_ctx, r->in.sid),
2626 ldb_errstring(state->pdb)));
2627 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2630 el = ldb_msg_find_element(res[0], "privilege");
2631 if (el == NULL || el->num_values == 0) {
2632 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2635 r->out.rights->count = el->num_values;
2636 r->out.rights->names = talloc_array(r->out.rights,
2637 struct lsa_StringLarge, r->out.rights->count);
2638 if (r->out.rights->names == NULL) {
2639 return NT_STATUS_NO_MEMORY;
2642 for (i=0;i<el->num_values;i++) {
2643 r->out.rights->names[i].string = (const char *)el->values[i].data;
2646 return NT_STATUS_OK;
2652 helper for lsa_AddAccountRights and lsa_RemoveAccountRights
2654 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
2655 TALLOC_CTX *mem_ctx,
2656 struct lsa_policy_state *state,
2657 int ldb_flag,
2658 struct dom_sid *sid,
2659 const struct lsa_RightSet *rights)
2661 const char *sidstr, *sidndrstr;
2662 struct ldb_message *msg;
2663 struct ldb_message_element *el;
2664 int ret;
2665 uint32_t i;
2666 struct lsa_EnumAccountRights r2;
2667 char *dnstr;
2669 if (security_session_user_level(dce_call->conn->auth_state.session_info, NULL) <
2670 SECURITY_ADMINISTRATOR) {
2671 DEBUG(0,("lsa_AddRemoveAccount refused for supplied security token\n"));
2672 return NT_STATUS_ACCESS_DENIED;
2675 msg = ldb_msg_new(mem_ctx);
2676 if (msg == NULL) {
2677 return NT_STATUS_NO_MEMORY;
2680 sidndrstr = ldap_encode_ndr_dom_sid(msg, sid);
2681 if (sidndrstr == NULL) {
2682 TALLOC_FREE(msg);
2683 return NT_STATUS_NO_MEMORY;
2686 sidstr = dom_sid_string(msg, sid);
2687 if (sidstr == NULL) {
2688 TALLOC_FREE(msg);
2689 return NT_STATUS_NO_MEMORY;
2692 dnstr = talloc_asprintf(msg, "sid=%s", sidstr);
2693 if (dnstr == NULL) {
2694 TALLOC_FREE(msg);
2695 return NT_STATUS_NO_MEMORY;
2698 msg->dn = ldb_dn_new(msg, state->pdb, dnstr);
2699 if (msg->dn == NULL) {
2700 TALLOC_FREE(msg);
2701 return NT_STATUS_NO_MEMORY;
2704 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2705 NTSTATUS status;
2707 r2.in.handle = &state->handle->wire_handle;
2708 r2.in.sid = sid;
2709 r2.out.rights = talloc(mem_ctx, struct lsa_RightSet);
2711 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
2712 if (!NT_STATUS_IS_OK(status)) {
2713 ZERO_STRUCTP(r2.out.rights);
2717 for (i=0;i<rights->count;i++) {
2718 if (sec_privilege_id(rights->names[i].string) == SEC_PRIV_INVALID) {
2719 if (sec_right_bit(rights->names[i].string) == 0) {
2720 talloc_free(msg);
2721 return NT_STATUS_NO_SUCH_PRIVILEGE;
2724 talloc_free(msg);
2725 return NT_STATUS_NO_SUCH_PRIVILEGE;
2728 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2729 uint32_t j;
2730 for (j=0;j<r2.out.rights->count;j++) {
2731 if (strcasecmp_m(r2.out.rights->names[j].string,
2732 rights->names[i].string) == 0) {
2733 break;
2736 if (j != r2.out.rights->count) continue;
2739 ret = ldb_msg_add_string(msg, "privilege", rights->names[i].string);
2740 if (ret != LDB_SUCCESS) {
2741 talloc_free(msg);
2742 return NT_STATUS_NO_MEMORY;
2746 el = ldb_msg_find_element(msg, "privilege");
2747 if (!el) {
2748 talloc_free(msg);
2749 return NT_STATUS_OK;
2752 el->flags = ldb_flag;
2754 ret = ldb_modify(state->pdb, msg);
2755 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
2756 if (samdb_msg_add_dom_sid(state->pdb, msg, msg, "objectSid", sid) != LDB_SUCCESS) {
2757 talloc_free(msg);
2758 return NT_STATUS_NO_MEMORY;
2760 ldb_msg_add_string(msg, "comment", "added via LSA");
2761 ret = ldb_add(state->pdb, msg);
2763 if (ret != LDB_SUCCESS) {
2764 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE && ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
2765 talloc_free(msg);
2766 return NT_STATUS_OK;
2768 DEBUG(3, ("Could not %s attributes from %s: %s",
2769 LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE ? "delete" : "add",
2770 ldb_dn_get_linearized(msg->dn), ldb_errstring(state->pdb)));
2771 talloc_free(msg);
2772 return NT_STATUS_UNEXPECTED_IO_ERROR;
2775 talloc_free(msg);
2776 return NT_STATUS_OK;
2780 lsa_AddPrivilegesToAccount
2782 static NTSTATUS dcesrv_lsa_AddPrivilegesToAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2783 struct lsa_AddPrivilegesToAccount *r)
2785 struct lsa_RightSet rights;
2786 struct dcesrv_handle *h;
2787 struct lsa_account_state *astate;
2788 uint32_t i;
2790 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2792 astate = h->data;
2794 rights.count = r->in.privs->count;
2795 rights.names = talloc_array(mem_ctx, struct lsa_StringLarge, rights.count);
2796 if (rights.names == NULL) {
2797 return NT_STATUS_NO_MEMORY;
2799 for (i=0;i<rights.count;i++) {
2800 int id = r->in.privs->set[i].luid.low;
2801 if (r->in.privs->set[i].luid.high) {
2802 return NT_STATUS_NO_SUCH_PRIVILEGE;
2804 rights.names[i].string = sec_privilege_name(id);
2805 if (rights.names[i].string == NULL) {
2806 return NT_STATUS_NO_SUCH_PRIVILEGE;
2810 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
2811 LDB_FLAG_MOD_ADD, astate->account_sid,
2812 &rights);
2817 lsa_RemovePrivilegesFromAccount
2819 static NTSTATUS dcesrv_lsa_RemovePrivilegesFromAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2820 struct lsa_RemovePrivilegesFromAccount *r)
2822 struct lsa_RightSet *rights;
2823 struct dcesrv_handle *h;
2824 struct lsa_account_state *astate;
2825 uint32_t i;
2827 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2829 astate = h->data;
2831 rights = talloc(mem_ctx, struct lsa_RightSet);
2833 if (r->in.remove_all == 1 &&
2834 r->in.privs == NULL) {
2835 struct lsa_EnumAccountRights r2;
2836 NTSTATUS status;
2838 r2.in.handle = &astate->policy->handle->wire_handle;
2839 r2.in.sid = astate->account_sid;
2840 r2.out.rights = rights;
2842 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
2843 if (!NT_STATUS_IS_OK(status)) {
2844 return status;
2847 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
2848 LDB_FLAG_MOD_DELETE, astate->account_sid,
2849 r2.out.rights);
2852 if (r->in.remove_all != 0) {
2853 return NT_STATUS_INVALID_PARAMETER;
2856 rights->count = r->in.privs->count;
2857 rights->names = talloc_array(mem_ctx, struct lsa_StringLarge, rights->count);
2858 if (rights->names == NULL) {
2859 return NT_STATUS_NO_MEMORY;
2861 for (i=0;i<rights->count;i++) {
2862 int id = r->in.privs->set[i].luid.low;
2863 if (r->in.privs->set[i].luid.high) {
2864 return NT_STATUS_NO_SUCH_PRIVILEGE;
2866 rights->names[i].string = sec_privilege_name(id);
2867 if (rights->names[i].string == NULL) {
2868 return NT_STATUS_NO_SUCH_PRIVILEGE;
2872 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
2873 LDB_FLAG_MOD_DELETE, astate->account_sid,
2874 rights);
2879 lsa_GetQuotasForAccount
2881 static NTSTATUS dcesrv_lsa_GetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2882 struct lsa_GetQuotasForAccount *r)
2884 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2889 lsa_SetQuotasForAccount
2891 static NTSTATUS dcesrv_lsa_SetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2892 struct lsa_SetQuotasForAccount *r)
2894 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2899 lsa_GetSystemAccessAccount
2901 static NTSTATUS dcesrv_lsa_GetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2902 struct lsa_GetSystemAccessAccount *r)
2904 struct dcesrv_handle *h;
2905 struct lsa_account_state *astate;
2906 int ret;
2907 unsigned int i;
2908 struct ldb_message **res;
2909 const char * const attrs[] = { "privilege", NULL};
2910 struct ldb_message_element *el;
2911 const char *sidstr;
2913 *(r->out.access_mask) = 0x00000000;
2915 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2917 astate = h->data;
2919 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
2920 if (sidstr == NULL) {
2921 return NT_STATUS_NO_MEMORY;
2924 ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs,
2925 "objectSid=%s", sidstr);
2926 if (ret < 0) {
2927 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2929 if (ret != 1) {
2930 return NT_STATUS_OK;
2933 el = ldb_msg_find_element(res[0], "privilege");
2934 if (el == NULL || el->num_values == 0) {
2935 return NT_STATUS_OK;
2938 for (i=0;i<el->num_values;i++) {
2939 uint32_t right_bit = sec_right_bit((const char *)el->values[i].data);
2940 if (right_bit == 0) {
2941 /* Perhaps an privilege, not a right */
2942 continue;
2944 *(r->out.access_mask) |= right_bit;
2947 return NT_STATUS_OK;
2952 lsa_SetSystemAccessAccount
2954 static NTSTATUS dcesrv_lsa_SetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2955 struct lsa_SetSystemAccessAccount *r)
2957 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2962 lsa_CreateSecret
2964 static NTSTATUS dcesrv_lsa_CreateSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2965 struct lsa_CreateSecret *r)
2967 struct dcesrv_handle *policy_handle;
2968 struct lsa_policy_state *policy_state;
2969 struct lsa_secret_state *secret_state;
2970 struct dcesrv_handle *handle;
2971 struct ldb_message **msgs, *msg;
2972 const char *attrs[] = {
2973 NULL
2976 const char *name;
2978 int ret;
2980 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2981 ZERO_STRUCTP(r->out.sec_handle);
2983 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
2985 case SECURITY_SYSTEM:
2986 case SECURITY_ADMINISTRATOR:
2987 break;
2988 default:
2989 /* Users and annonymous are not allowed create secrets */
2990 return NT_STATUS_ACCESS_DENIED;
2993 policy_state = policy_handle->data;
2995 if (!r->in.name.string) {
2996 return NT_STATUS_INVALID_PARAMETER;
2999 secret_state = talloc(mem_ctx, struct lsa_secret_state);
3000 NT_STATUS_HAVE_NO_MEMORY(secret_state);
3001 secret_state->policy = policy_state;
3003 msg = ldb_msg_new(mem_ctx);
3004 if (msg == NULL) {
3005 return NT_STATUS_NO_MEMORY;
3008 if (strncmp("G$", r->in.name.string, 2) == 0) {
3009 const char *name2;
3011 secret_state->global = true;
3013 name = &r->in.name.string[2];
3014 if (strlen(name) == 0) {
3015 return NT_STATUS_INVALID_PARAMETER;
3018 name2 = talloc_asprintf(mem_ctx, "%s Secret",
3019 ldb_binary_encode_string(mem_ctx, name));
3020 NT_STATUS_HAVE_NO_MEMORY(name2);
3022 /* We need to connect to the database as system, as this is one
3023 * of the rare RPC calls that must read the secrets (and this
3024 * is denied otherwise) */
3025 secret_state->sam_ldb = talloc_reference(secret_state,
3026 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));
3027 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
3029 /* search for the secret record */
3030 ret = gendb_search(secret_state->sam_ldb,
3031 mem_ctx, policy_state->system_dn, &msgs, attrs,
3032 "(&(cn=%s)(objectclass=secret))",
3033 name2);
3034 if (ret > 0) {
3035 return NT_STATUS_OBJECT_NAME_COLLISION;
3038 if (ret < 0) {
3039 DEBUG(0,("Failure searching for CN=%s: %s\n",
3040 name2, ldb_errstring(secret_state->sam_ldb)));
3041 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3044 msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
3045 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
3046 if (!ldb_dn_add_child_fmt(msg->dn, "cn=%s", name2)) {
3047 return NT_STATUS_NO_MEMORY;
3050 ret = ldb_msg_add_string(msg, "cn", name2);
3051 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
3052 } else {
3053 secret_state->global = false;
3055 name = r->in.name.string;
3056 if (strlen(name) == 0) {
3057 return NT_STATUS_INVALID_PARAMETER;
3060 secret_state->sam_ldb = talloc_reference(secret_state,
3061 secrets_db_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
3062 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
3064 /* search for the secret record */
3065 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
3066 ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
3067 &msgs, attrs,
3068 "(&(cn=%s)(objectclass=secret))",
3069 ldb_binary_encode_string(mem_ctx, name));
3070 if (ret > 0) {
3071 return NT_STATUS_OBJECT_NAME_COLLISION;
3074 if (ret < 0) {
3075 DEBUG(0,("Failure searching for CN=%s: %s\n",
3076 name, ldb_errstring(secret_state->sam_ldb)));
3077 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3080 msg->dn = ldb_dn_new_fmt(mem_ctx, secret_state->sam_ldb,
3081 "cn=%s,cn=LSA Secrets", name);
3082 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
3083 ret = ldb_msg_add_string(msg, "cn", name);
3084 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
3087 ret = ldb_msg_add_string(msg, "objectClass", "secret");
3088 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
3090 secret_state->secret_dn = talloc_reference(secret_state, msg->dn);
3091 NT_STATUS_HAVE_NO_MEMORY(secret_state->secret_dn);
3093 /* create the secret */
3094 ret = ldb_add(secret_state->sam_ldb, msg);
3095 if (ret != LDB_SUCCESS) {
3096 DEBUG(0,("Failed to create secret record %s: %s\n",
3097 ldb_dn_get_linearized(msg->dn),
3098 ldb_errstring(secret_state->sam_ldb)));
3099 return NT_STATUS_ACCESS_DENIED;
3102 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
3103 NT_STATUS_HAVE_NO_MEMORY(handle);
3105 handle->data = talloc_steal(handle, secret_state);
3107 secret_state->access_mask = r->in.access_mask;
3108 secret_state->policy = talloc_reference(secret_state, policy_state);
3109 NT_STATUS_HAVE_NO_MEMORY(secret_state->policy);
3111 *r->out.sec_handle = handle->wire_handle;
3113 return NT_STATUS_OK;
3118 lsa_OpenSecret
3120 static NTSTATUS dcesrv_lsa_OpenSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3121 struct lsa_OpenSecret *r)
3123 struct dcesrv_handle *policy_handle;
3125 struct lsa_policy_state *policy_state;
3126 struct lsa_secret_state *secret_state;
3127 struct dcesrv_handle *handle;
3128 struct ldb_message **msgs;
3129 const char *attrs[] = {
3130 NULL
3133 const char *name;
3135 int ret;
3137 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
3138 ZERO_STRUCTP(r->out.sec_handle);
3139 policy_state = policy_handle->data;
3141 if (!r->in.name.string) {
3142 return NT_STATUS_INVALID_PARAMETER;
3145 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3147 case SECURITY_SYSTEM:
3148 case SECURITY_ADMINISTRATOR:
3149 break;
3150 default:
3151 /* Users and annonymous are not allowed to access secrets */
3152 return NT_STATUS_ACCESS_DENIED;
3155 secret_state = talloc(mem_ctx, struct lsa_secret_state);
3156 if (!secret_state) {
3157 return NT_STATUS_NO_MEMORY;
3159 secret_state->policy = policy_state;
3161 if (strncmp("G$", r->in.name.string, 2) == 0) {
3162 name = &r->in.name.string[2];
3163 /* 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) */
3164 secret_state->sam_ldb = talloc_reference(secret_state,
3165 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));
3166 secret_state->global = true;
3168 if (strlen(name) < 1) {
3169 return NT_STATUS_INVALID_PARAMETER;
3172 /* search for the secret record */
3173 ret = gendb_search(secret_state->sam_ldb,
3174 mem_ctx, policy_state->system_dn, &msgs, attrs,
3175 "(&(cn=%s Secret)(objectclass=secret))",
3176 ldb_binary_encode_string(mem_ctx, name));
3177 if (ret == 0) {
3178 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3181 if (ret != 1) {
3182 DEBUG(0,("Found %d records matching DN %s\n", ret,
3183 ldb_dn_get_linearized(policy_state->system_dn)));
3184 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3186 } else {
3187 secret_state->global = false;
3188 secret_state->sam_ldb = talloc_reference(secret_state,
3189 secrets_db_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
3191 name = r->in.name.string;
3192 if (strlen(name) < 1) {
3193 return NT_STATUS_INVALID_PARAMETER;
3196 /* search for the secret record */
3197 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
3198 ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
3199 &msgs, attrs,
3200 "(&(cn=%s)(objectclass=secret))",
3201 ldb_binary_encode_string(mem_ctx, name));
3202 if (ret == 0) {
3203 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3206 if (ret != 1) {
3207 DEBUG(0,("Found %d records matching CN=%s\n",
3208 ret, ldb_binary_encode_string(mem_ctx, name)));
3209 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3213 secret_state->secret_dn = talloc_reference(secret_state, msgs[0]->dn);
3215 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
3216 if (!handle) {
3217 return NT_STATUS_NO_MEMORY;
3220 handle->data = talloc_steal(handle, secret_state);
3222 secret_state->access_mask = r->in.access_mask;
3223 secret_state->policy = talloc_reference(secret_state, policy_state);
3225 *r->out.sec_handle = handle->wire_handle;
3227 return NT_STATUS_OK;
3232 lsa_SetSecret
3234 static NTSTATUS dcesrv_lsa_SetSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3235 struct lsa_SetSecret *r)
3238 struct dcesrv_handle *h;
3239 struct lsa_secret_state *secret_state;
3240 struct ldb_message *msg;
3241 DATA_BLOB session_key;
3242 DATA_BLOB crypt_secret, secret;
3243 struct ldb_val val;
3244 int ret;
3245 NTSTATUS status = NT_STATUS_OK;
3247 struct timeval now = timeval_current();
3248 NTTIME nt_now = timeval_to_nttime(&now);
3250 DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3252 secret_state = h->data;
3254 msg = ldb_msg_new(mem_ctx);
3255 if (msg == NULL) {
3256 return NT_STATUS_NO_MEMORY;
3259 msg->dn = talloc_reference(mem_ctx, secret_state->secret_dn);
3260 if (!msg->dn) {
3261 return NT_STATUS_NO_MEMORY;
3263 status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
3264 if (!NT_STATUS_IS_OK(status)) {
3265 return status;
3268 if (r->in.old_val) {
3269 /* Decrypt */
3270 crypt_secret.data = r->in.old_val->data;
3271 crypt_secret.length = r->in.old_val->size;
3273 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3274 if (!NT_STATUS_IS_OK(status)) {
3275 return status;
3278 val.data = secret.data;
3279 val.length = secret.length;
3281 /* set value */
3282 if (ldb_msg_add_value(msg, "priorValue", &val, NULL) != LDB_SUCCESS) {
3283 return NT_STATUS_NO_MEMORY;
3286 /* set old value mtime */
3287 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3288 mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3289 return NT_STATUS_NO_MEMORY;
3292 } else {
3293 /* If the old value is not set, then migrate the
3294 * current value to the old value */
3295 const struct ldb_val *old_val;
3296 NTTIME last_set_time;
3297 struct ldb_message **res;
3298 const char *attrs[] = {
3299 "currentValue",
3300 "lastSetTime",
3301 NULL
3304 /* search for the secret record */
3305 ret = gendb_search_dn(secret_state->sam_ldb,mem_ctx,
3306 secret_state->secret_dn, &res, attrs);
3307 if (ret == 0) {
3308 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3311 if (ret != 1) {
3312 DEBUG(0,("Found %d records matching dn=%s\n", ret,
3313 ldb_dn_get_linearized(secret_state->secret_dn)));
3314 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3317 old_val = ldb_msg_find_ldb_val(res[0], "currentValue");
3318 last_set_time = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
3320 if (old_val) {
3321 /* set old value */
3322 if (ldb_msg_add_value(msg, "priorValue",
3323 old_val, NULL) != LDB_SUCCESS) {
3324 return NT_STATUS_NO_MEMORY;
3326 } else {
3327 if (samdb_msg_add_delete(secret_state->sam_ldb,
3328 mem_ctx, msg, "priorValue") != LDB_SUCCESS) {
3329 return NT_STATUS_NO_MEMORY;
3333 /* set old value mtime */
3334 if (ldb_msg_find_ldb_val(res[0], "lastSetTime")) {
3335 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3336 mem_ctx, msg, "priorSetTime", last_set_time) != LDB_SUCCESS) {
3337 return NT_STATUS_NO_MEMORY;
3339 } else {
3340 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3341 mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3342 return NT_STATUS_NO_MEMORY;
3347 if (r->in.new_val) {
3348 /* Decrypt */
3349 crypt_secret.data = r->in.new_val->data;
3350 crypt_secret.length = r->in.new_val->size;
3352 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3353 if (!NT_STATUS_IS_OK(status)) {
3354 return status;
3357 val.data = secret.data;
3358 val.length = secret.length;
3360 /* set value */
3361 if (ldb_msg_add_value(msg, "currentValue", &val, NULL) != LDB_SUCCESS) {
3362 return NT_STATUS_NO_MEMORY;
3365 /* set new value mtime */
3366 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3367 mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3368 return NT_STATUS_NO_MEMORY;
3370 } else {
3371 /* NULL out the NEW value */
3372 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3373 mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3374 return NT_STATUS_NO_MEMORY;
3376 if (samdb_msg_add_delete(secret_state->sam_ldb,
3377 mem_ctx, msg, "currentValue") != LDB_SUCCESS) {
3378 return NT_STATUS_NO_MEMORY;
3382 /* modify the samdb record */
3383 ret = dsdb_replace(secret_state->sam_ldb, msg, 0);
3384 if (ret != LDB_SUCCESS) {
3385 return dsdb_ldb_err_to_ntstatus(ret);
3388 return NT_STATUS_OK;
3393 lsa_QuerySecret
3395 static NTSTATUS dcesrv_lsa_QuerySecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3396 struct lsa_QuerySecret *r)
3398 struct dcesrv_handle *h;
3399 struct lsa_secret_state *secret_state;
3400 struct ldb_message *msg;
3401 DATA_BLOB session_key;
3402 DATA_BLOB crypt_secret, secret;
3403 int ret;
3404 struct ldb_message **res;
3405 const char *attrs[] = {
3406 "currentValue",
3407 "priorValue",
3408 "lastSetTime",
3409 "priorSetTime",
3410 NULL
3413 NTSTATUS nt_status;
3415 DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3417 /* Ensure user is permitted to read this... */
3418 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3420 case SECURITY_SYSTEM:
3421 case SECURITY_ADMINISTRATOR:
3422 break;
3423 default:
3424 /* Users and annonymous are not allowed to read secrets */
3425 return NT_STATUS_ACCESS_DENIED;
3428 secret_state = h->data;
3430 /* pull all the user attributes */
3431 ret = gendb_search_dn(secret_state->sam_ldb, mem_ctx,
3432 secret_state->secret_dn, &res, attrs);
3433 if (ret != 1) {
3434 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3436 msg = res[0];
3438 nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
3439 if (!NT_STATUS_IS_OK(nt_status)) {
3440 return nt_status;
3443 if (r->in.old_val) {
3444 const struct ldb_val *prior_val;
3445 r->out.old_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3446 if (!r->out.old_val) {
3447 return NT_STATUS_NO_MEMORY;
3449 prior_val = ldb_msg_find_ldb_val(msg, "priorValue");
3451 if (prior_val && prior_val->length) {
3452 secret.data = prior_val->data;
3453 secret.length = prior_val->length;
3455 /* Encrypt */
3456 crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3457 if (!crypt_secret.length) {
3458 return NT_STATUS_NO_MEMORY;
3460 r->out.old_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3461 if (!r->out.old_val->buf) {
3462 return NT_STATUS_NO_MEMORY;
3464 r->out.old_val->buf->size = crypt_secret.length;
3465 r->out.old_val->buf->length = crypt_secret.length;
3466 r->out.old_val->buf->data = crypt_secret.data;
3470 if (r->in.old_mtime) {
3471 r->out.old_mtime = talloc(mem_ctx, NTTIME);
3472 if (!r->out.old_mtime) {
3473 return NT_STATUS_NO_MEMORY;
3475 *r->out.old_mtime = ldb_msg_find_attr_as_uint64(msg, "priorSetTime", 0);
3478 if (r->in.new_val) {
3479 const struct ldb_val *new_val;
3480 r->out.new_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3481 if (!r->out.new_val) {
3482 return NT_STATUS_NO_MEMORY;
3485 new_val = ldb_msg_find_ldb_val(msg, "currentValue");
3487 if (new_val && new_val->length) {
3488 secret.data = new_val->data;
3489 secret.length = new_val->length;
3491 /* Encrypt */
3492 crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3493 if (!crypt_secret.length) {
3494 return NT_STATUS_NO_MEMORY;
3496 r->out.new_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3497 if (!r->out.new_val->buf) {
3498 return NT_STATUS_NO_MEMORY;
3500 r->out.new_val->buf->length = crypt_secret.length;
3501 r->out.new_val->buf->size = crypt_secret.length;
3502 r->out.new_val->buf->data = crypt_secret.data;
3506 if (r->in.new_mtime) {
3507 r->out.new_mtime = talloc(mem_ctx, NTTIME);
3508 if (!r->out.new_mtime) {
3509 return NT_STATUS_NO_MEMORY;
3511 *r->out.new_mtime = ldb_msg_find_attr_as_uint64(msg, "lastSetTime", 0);
3514 return NT_STATUS_OK;
3519 lsa_LookupPrivValue
3521 static NTSTATUS dcesrv_lsa_LookupPrivValue(struct dcesrv_call_state *dce_call,
3522 TALLOC_CTX *mem_ctx,
3523 struct lsa_LookupPrivValue *r)
3525 struct dcesrv_handle *h;
3526 int id;
3528 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3530 id = sec_privilege_id(r->in.name->string);
3531 if (id == SEC_PRIV_INVALID) {
3532 return NT_STATUS_NO_SUCH_PRIVILEGE;
3535 r->out.luid->low = id;
3536 r->out.luid->high = 0;
3538 return NT_STATUS_OK;
3543 lsa_LookupPrivName
3545 static NTSTATUS dcesrv_lsa_LookupPrivName(struct dcesrv_call_state *dce_call,
3546 TALLOC_CTX *mem_ctx,
3547 struct lsa_LookupPrivName *r)
3549 struct dcesrv_handle *h;
3550 struct lsa_StringLarge *name;
3551 const char *privname;
3553 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3555 if (r->in.luid->high != 0) {
3556 return NT_STATUS_NO_SUCH_PRIVILEGE;
3559 privname = sec_privilege_name(r->in.luid->low);
3560 if (privname == NULL) {
3561 return NT_STATUS_NO_SUCH_PRIVILEGE;
3564 name = talloc(mem_ctx, struct lsa_StringLarge);
3565 if (name == NULL) {
3566 return NT_STATUS_NO_MEMORY;
3569 name->string = privname;
3571 *r->out.name = name;
3573 return NT_STATUS_OK;
3578 lsa_LookupPrivDisplayName
3580 static NTSTATUS dcesrv_lsa_LookupPrivDisplayName(struct dcesrv_call_state *dce_call,
3581 TALLOC_CTX *mem_ctx,
3582 struct lsa_LookupPrivDisplayName *r)
3584 struct dcesrv_handle *h;
3585 struct lsa_StringLarge *disp_name = NULL;
3586 enum sec_privilege id;
3588 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3590 id = sec_privilege_id(r->in.name->string);
3591 if (id == SEC_PRIV_INVALID) {
3592 return NT_STATUS_NO_SUCH_PRIVILEGE;
3595 disp_name = talloc(mem_ctx, struct lsa_StringLarge);
3596 if (disp_name == NULL) {
3597 return NT_STATUS_NO_MEMORY;
3600 disp_name->string = sec_privilege_display_name(id, &r->in.language_id);
3601 if (disp_name->string == NULL) {
3602 return NT_STATUS_INTERNAL_ERROR;
3605 *r->out.disp_name = disp_name;
3606 *r->out.returned_language_id = 0;
3608 return NT_STATUS_OK;
3613 lsa_EnumAccountsWithUserRight
3615 static NTSTATUS dcesrv_lsa_EnumAccountsWithUserRight(struct dcesrv_call_state *dce_call,
3616 TALLOC_CTX *mem_ctx,
3617 struct lsa_EnumAccountsWithUserRight *r)
3619 struct dcesrv_handle *h;
3620 struct lsa_policy_state *state;
3621 int ret, i;
3622 struct ldb_message **res;
3623 const char * const attrs[] = { "objectSid", NULL};
3624 const char *privname;
3626 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3628 state = h->data;
3630 if (r->in.name == NULL) {
3631 return NT_STATUS_NO_SUCH_PRIVILEGE;
3634 privname = r->in.name->string;
3635 if (sec_privilege_id(privname) == SEC_PRIV_INVALID && sec_right_bit(privname) == 0) {
3636 return NT_STATUS_NO_SUCH_PRIVILEGE;
3639 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
3640 "privilege=%s", privname);
3641 if (ret < 0) {
3642 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3644 if (ret == 0) {
3645 return NT_STATUS_NO_MORE_ENTRIES;
3648 r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, ret);
3649 if (r->out.sids->sids == NULL) {
3650 return NT_STATUS_NO_MEMORY;
3652 for (i=0;i<ret;i++) {
3653 r->out.sids->sids[i].sid = samdb_result_dom_sid(r->out.sids->sids,
3654 res[i], "objectSid");
3655 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
3657 r->out.sids->num_sids = ret;
3659 return NT_STATUS_OK;
3664 lsa_AddAccountRights
3666 static NTSTATUS dcesrv_lsa_AddAccountRights(struct dcesrv_call_state *dce_call,
3667 TALLOC_CTX *mem_ctx,
3668 struct lsa_AddAccountRights *r)
3670 struct dcesrv_handle *h;
3671 struct lsa_policy_state *state;
3673 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3675 state = h->data;
3677 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3678 LDB_FLAG_MOD_ADD,
3679 r->in.sid, r->in.rights);
3684 lsa_RemoveAccountRights
3686 static NTSTATUS dcesrv_lsa_RemoveAccountRights(struct dcesrv_call_state *dce_call,
3687 TALLOC_CTX *mem_ctx,
3688 struct lsa_RemoveAccountRights *r)
3690 struct dcesrv_handle *h;
3691 struct lsa_policy_state *state;
3693 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3695 state = h->data;
3697 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3698 LDB_FLAG_MOD_DELETE,
3699 r->in.sid, r->in.rights);
3704 lsa_StorePrivateData
3706 static NTSTATUS dcesrv_lsa_StorePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3707 struct lsa_StorePrivateData *r)
3709 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3714 lsa_RetrievePrivateData
3716 static NTSTATUS dcesrv_lsa_RetrievePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3717 struct lsa_RetrievePrivateData *r)
3719 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3724 lsa_GetUserName
3726 static NTSTATUS dcesrv_lsa_GetUserName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3727 struct lsa_GetUserName *r)
3729 enum dcerpc_transport_t transport =
3730 dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description);
3731 NTSTATUS status = NT_STATUS_OK;
3732 const char *account_name;
3733 const char *authority_name;
3734 struct lsa_String *_account_name;
3735 struct lsa_String *_authority_name = NULL;
3737 if (transport != NCACN_NP && transport != NCALRPC) {
3738 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
3741 /* this is what w2k3 does */
3742 r->out.account_name = r->in.account_name;
3743 r->out.authority_name = r->in.authority_name;
3745 if (r->in.account_name
3746 && *r->in.account_name
3747 /* && *(*r->in.account_name)->string */
3749 return NT_STATUS_INVALID_PARAMETER;
3752 if (r->in.authority_name
3753 && *r->in.authority_name
3754 /* && *(*r->in.authority_name)->string */
3756 return NT_STATUS_INVALID_PARAMETER;
3759 account_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->info->account_name);
3760 authority_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->info->domain_name);
3762 _account_name = talloc(mem_ctx, struct lsa_String);
3763 NT_STATUS_HAVE_NO_MEMORY(_account_name);
3764 _account_name->string = account_name;
3766 if (r->in.authority_name) {
3767 _authority_name = talloc(mem_ctx, struct lsa_String);
3768 NT_STATUS_HAVE_NO_MEMORY(_authority_name);
3769 _authority_name->string = authority_name;
3772 *r->out.account_name = _account_name;
3773 if (r->out.authority_name) {
3774 *r->out.authority_name = _authority_name;
3777 return status;
3781 lsa_SetInfoPolicy2
3783 static NTSTATUS dcesrv_lsa_SetInfoPolicy2(struct dcesrv_call_state *dce_call,
3784 TALLOC_CTX *mem_ctx,
3785 struct lsa_SetInfoPolicy2 *r)
3787 /* need to support these */
3788 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3791 static void kdc_get_policy(struct loadparm_context *lp_ctx,
3792 struct smb_krb5_context *smb_krb5_context,
3793 struct lsa_DomainInfoKerberos *k)
3795 time_t svc_tkt_lifetime;
3796 time_t usr_tkt_lifetime;
3797 time_t renewal_lifetime;
3799 /* These should be set and stored via Group Policy, but until then, some defaults are in order */
3801 /* Our KDC always re-validates the client */
3802 k->authentication_options = LSA_POLICY_KERBEROS_VALIDATE_CLIENT;
3804 lpcfg_default_kdc_policy(lp_ctx, &svc_tkt_lifetime,
3805 &usr_tkt_lifetime, &renewal_lifetime);
3807 unix_to_nt_time(&k->service_tkt_lifetime, svc_tkt_lifetime);
3808 unix_to_nt_time(&k->user_tkt_lifetime, usr_tkt_lifetime);
3809 unix_to_nt_time(&k->user_tkt_renewaltime, renewal_lifetime);
3810 #ifdef SAMBA4_USES_HEIMDAL /* MIT lacks krb5_get_max_time_skew.
3811 However in the parent function we basically just did a full
3812 krb5_context init with the only purpose of getting a global
3813 config option (the max skew), it would probably make more sense
3814 to have a lp_ or ldb global option as the samba default */
3815 if (smb_krb5_context) {
3816 unix_to_nt_time(&k->clock_skew,
3817 krb5_get_max_time_skew(smb_krb5_context->krb5_context));
3819 #endif
3820 k->reserved = 0;
3823 lsa_QueryDomainInformationPolicy
3825 static NTSTATUS dcesrv_lsa_QueryDomainInformationPolicy(struct dcesrv_call_state *dce_call,
3826 TALLOC_CTX *mem_ctx,
3827 struct lsa_QueryDomainInformationPolicy *r)
3829 union lsa_DomainInformationPolicy *info;
3831 info = talloc_zero(r->out.info, union lsa_DomainInformationPolicy);
3832 if (!info) {
3833 return NT_STATUS_NO_MEMORY;
3836 switch (r->in.level) {
3837 case LSA_DOMAIN_INFO_POLICY_EFS:
3838 talloc_free(info);
3839 *r->out.info = NULL;
3840 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3841 case LSA_DOMAIN_INFO_POLICY_KERBEROS:
3843 struct lsa_DomainInfoKerberos *k = &info->kerberos_info;
3844 struct smb_krb5_context *smb_krb5_context;
3845 int ret = smb_krb5_init_context(mem_ctx,
3846 dce_call->conn->dce_ctx->lp_ctx,
3847 &smb_krb5_context);
3848 if (ret != 0) {
3849 talloc_free(info);
3850 *r->out.info = NULL;
3851 return NT_STATUS_INTERNAL_ERROR;
3853 kdc_get_policy(dce_call->conn->dce_ctx->lp_ctx,
3854 smb_krb5_context,
3856 talloc_free(smb_krb5_context);
3857 *r->out.info = info;
3858 return NT_STATUS_OK;
3860 default:
3861 talloc_free(info);
3862 *r->out.info = NULL;
3863 return NT_STATUS_INVALID_INFO_CLASS;
3868 lsa_SetDomInfoPolicy
3870 static NTSTATUS dcesrv_lsa_SetDomainInformationPolicy(struct dcesrv_call_state *dce_call,
3871 TALLOC_CTX *mem_ctx,
3872 struct lsa_SetDomainInformationPolicy *r)
3874 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3878 lsa_TestCall
3880 static NTSTATUS dcesrv_lsa_TestCall(struct dcesrv_call_state *dce_call,
3881 TALLOC_CTX *mem_ctx,
3882 struct lsa_TestCall *r)
3884 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3888 lsa_CREDRWRITE
3890 static NTSTATUS dcesrv_lsa_CREDRWRITE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3891 struct lsa_CREDRWRITE *r)
3893 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3898 lsa_CREDRREAD
3900 static NTSTATUS dcesrv_lsa_CREDRREAD(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3901 struct lsa_CREDRREAD *r)
3903 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3908 lsa_CREDRENUMERATE
3910 static NTSTATUS dcesrv_lsa_CREDRENUMERATE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3911 struct lsa_CREDRENUMERATE *r)
3913 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3918 lsa_CREDRWRITEDOMAINCREDENTIALS
3920 static NTSTATUS dcesrv_lsa_CREDRWRITEDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3921 struct lsa_CREDRWRITEDOMAINCREDENTIALS *r)
3923 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3928 lsa_CREDRREADDOMAINCREDENTIALS
3930 static NTSTATUS dcesrv_lsa_CREDRREADDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3931 struct lsa_CREDRREADDOMAINCREDENTIALS *r)
3933 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3938 lsa_CREDRDELETE
3940 static NTSTATUS dcesrv_lsa_CREDRDELETE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3941 struct lsa_CREDRDELETE *r)
3943 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3948 lsa_CREDRGETTARGETINFO
3950 static NTSTATUS dcesrv_lsa_CREDRGETTARGETINFO(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3951 struct lsa_CREDRGETTARGETINFO *r)
3953 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3958 lsa_CREDRPROFILELOADED
3960 static NTSTATUS dcesrv_lsa_CREDRPROFILELOADED(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3961 struct lsa_CREDRPROFILELOADED *r)
3963 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3968 lsa_CREDRGETSESSIONTYPES
3970 static NTSTATUS dcesrv_lsa_CREDRGETSESSIONTYPES(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3971 struct lsa_CREDRGETSESSIONTYPES *r)
3973 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3978 lsa_LSARREGISTERAUDITEVENT
3980 static NTSTATUS dcesrv_lsa_LSARREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3981 struct lsa_LSARREGISTERAUDITEVENT *r)
3983 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3988 lsa_LSARGENAUDITEVENT
3990 static NTSTATUS dcesrv_lsa_LSARGENAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3991 struct lsa_LSARGENAUDITEVENT *r)
3993 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3998 lsa_LSARUNREGISTERAUDITEVENT
4000 static NTSTATUS dcesrv_lsa_LSARUNREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4001 struct lsa_LSARUNREGISTERAUDITEVENT *r)
4003 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4008 lsa_lsaRQueryForestTrustInformation
4010 static NTSTATUS dcesrv_lsa_lsaRQueryForestTrustInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4011 struct lsa_lsaRQueryForestTrustInformation *r)
4013 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4016 #define DNS_CMP_MATCH 0
4017 #define DNS_CMP_FIRST_IS_CHILD 1
4018 #define DNS_CMP_SECOND_IS_CHILD 2
4019 #define DNS_CMP_NO_MATCH 3
4021 /* this function assumes names are well formed DNS names.
4022 * it doesn't validate them */
4023 static int dns_cmp(const char *s1, size_t l1,
4024 const char *s2, size_t l2)
4026 const char *p1, *p2;
4027 size_t t1, t2;
4028 int cret;
4030 if (l1 == l2) {
4031 if (strcasecmp_m(s1, s2) == 0) {
4032 return DNS_CMP_MATCH;
4034 return DNS_CMP_NO_MATCH;
4037 if (l1 > l2) {
4038 p1 = s1;
4039 p2 = s2;
4040 t1 = l1;
4041 t2 = l2;
4042 cret = DNS_CMP_FIRST_IS_CHILD;
4043 } else {
4044 p1 = s2;
4045 p2 = s1;
4046 t1 = l2;
4047 t2 = l1;
4048 cret = DNS_CMP_SECOND_IS_CHILD;
4051 if (p1[t1 - t2 - 1] != '.') {
4052 return DNS_CMP_NO_MATCH;
4055 if (strcasecmp_m(&p1[t1 - t2], p2) == 0) {
4056 return cret;
4059 return DNS_CMP_NO_MATCH;
4062 /* decode all TDOs forest trust info blobs */
4063 static NTSTATUS get_ft_info(TALLOC_CTX *mem_ctx,
4064 struct ldb_message *msg,
4065 struct ForestTrustInfo *info)
4067 const struct ldb_val *ft_blob;
4068 enum ndr_err_code ndr_err;
4070 ft_blob = ldb_msg_find_ldb_val(msg, "msDS-TrustForestTrustInfo");
4071 if (!ft_blob || !ft_blob->data) {
4072 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4074 /* ldb_val is equivalent to DATA_BLOB */
4075 ndr_err = ndr_pull_struct_blob_all(ft_blob, mem_ctx, info,
4076 (ndr_pull_flags_fn_t)ndr_pull_ForestTrustInfo);
4077 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
4078 return NT_STATUS_INVALID_DOMAIN_STATE;
4081 return NT_STATUS_OK;
4084 static NTSTATUS own_ft_info(struct lsa_policy_state *ps,
4085 struct ForestTrustInfo *fti)
4087 struct ForestTrustDataDomainInfo *info;
4088 struct ForestTrustInfoRecord *rec;
4090 fti->version = 1;
4091 fti->count = 2;
4092 fti->records = talloc_array(fti,
4093 struct ForestTrustInfoRecordArmor, 2);
4094 if (!fti->records) {
4095 return NT_STATUS_NO_MEMORY;
4098 /* TLN info */
4099 rec = &fti->records[0].record;
4101 rec->flags = 0;
4102 rec->timestamp = 0;
4103 rec->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
4105 rec->data.name.string = talloc_strdup(fti, ps->forest_dns);
4106 if (!rec->data.name.string) {
4107 return NT_STATUS_NO_MEMORY;
4109 rec->data.name.size = strlen(rec->data.name.string);
4111 /* DOMAIN info */
4112 rec = &fti->records[1].record;
4114 rec->flags = 0;
4115 rec->timestamp = 0;
4116 rec->type = LSA_FOREST_TRUST_DOMAIN_INFO;
4118 info = &rec->data.info;
4120 info->sid = *ps->domain_sid;
4121 info->dns_name.string = talloc_strdup(fti, ps->domain_dns);
4122 if (!info->dns_name.string) {
4123 return NT_STATUS_NO_MEMORY;
4125 info->dns_name.size = strlen(info->dns_name.string);
4126 info->netbios_name.string = talloc_strdup(fti, ps->domain_name);
4127 if (!info->netbios_name.string) {
4128 return NT_STATUS_NO_MEMORY;
4130 info->netbios_name.size = strlen(info->netbios_name.string);
4132 return NT_STATUS_OK;
4135 static NTSTATUS make_ft_info(TALLOC_CTX *mem_ctx,
4136 struct lsa_ForestTrustInformation *lfti,
4137 struct ForestTrustInfo *fti)
4139 struct lsa_ForestTrustRecord *lrec;
4140 struct ForestTrustInfoRecord *rec;
4141 struct lsa_StringLarge *tln;
4142 struct lsa_ForestTrustDomainInfo *info;
4143 uint32_t i;
4145 fti->version = 1;
4146 fti->count = lfti->count;
4147 fti->records = talloc_array(mem_ctx,
4148 struct ForestTrustInfoRecordArmor,
4149 fti->count);
4150 if (!fti->records) {
4151 return NT_STATUS_NO_MEMORY;
4153 for (i = 0; i < fti->count; i++) {
4154 lrec = lfti->entries[i];
4155 rec = &fti->records[i].record;
4157 rec->flags = lrec->flags;
4158 rec->timestamp = lrec->time;
4159 rec->type = lrec->type;
4161 switch (lrec->type) {
4162 case LSA_FOREST_TRUST_TOP_LEVEL_NAME:
4163 case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
4164 tln = &lrec->forest_trust_data.top_level_name;
4165 rec->data.name.string =
4166 talloc_strdup(mem_ctx, tln->string);
4167 if (!rec->data.name.string) {
4168 return NT_STATUS_NO_MEMORY;
4170 rec->data.name.size = strlen(rec->data.name.string);
4171 break;
4172 case LSA_FOREST_TRUST_DOMAIN_INFO:
4173 info = &lrec->forest_trust_data.domain_info;
4174 rec->data.info.sid = *info->domain_sid;
4175 rec->data.info.dns_name.string =
4176 talloc_strdup(mem_ctx,
4177 info->dns_domain_name.string);
4178 if (!rec->data.info.dns_name.string) {
4179 return NT_STATUS_NO_MEMORY;
4181 rec->data.info.dns_name.size =
4182 strlen(rec->data.info.dns_name.string);
4183 rec->data.info.netbios_name.string =
4184 talloc_strdup(mem_ctx,
4185 info->netbios_domain_name.string);
4186 if (!rec->data.info.netbios_name.string) {
4187 return NT_STATUS_NO_MEMORY;
4189 rec->data.info.netbios_name.size =
4190 strlen(rec->data.info.netbios_name.string);
4191 break;
4192 default:
4193 return NT_STATUS_INVALID_DOMAIN_STATE;
4197 return NT_STATUS_OK;
4200 static NTSTATUS add_collision(struct lsa_ForestTrustCollisionInfo *c_info,
4201 uint32_t idx, uint32_t collision_type,
4202 uint32_t conflict_type, const char *tdo_name);
4204 static NTSTATUS check_ft_info(TALLOC_CTX *mem_ctx,
4205 const char *tdo_name,
4206 struct ForestTrustInfo *tdo_fti,
4207 struct ForestTrustInfo *new_fti,
4208 struct lsa_ForestTrustCollisionInfo *c_info)
4210 struct ForestTrustInfoRecord *nrec;
4211 struct ForestTrustInfoRecord *trec;
4212 const char *dns_name;
4213 const char *nb_name;
4214 struct dom_sid *sid = NULL;
4215 const char *tname = NULL;
4216 size_t dns_len;
4217 size_t tlen = 0;
4218 NTSTATUS nt_status = NT_STATUS_OK;
4219 uint32_t new_fti_idx;
4220 uint32_t i;
4221 /* use always TDO type, until we understand when Xref can be used */
4222 uint32_t collision_type = LSA_FOREST_TRUST_COLLISION_TDO;
4223 bool tln_conflict;
4224 bool sid_conflict;
4225 bool nb_conflict;
4226 bool exclusion;
4227 bool ex_rule = false;
4228 int ret;
4230 for (new_fti_idx = 0; new_fti_idx < new_fti->count; new_fti_idx++) {
4232 nrec = &new_fti->records[new_fti_idx].record;
4233 dns_name = NULL;
4234 nb_name = NULL;
4235 tln_conflict = false;
4236 sid_conflict = false;
4237 nb_conflict = false;
4238 exclusion = false;
4240 switch (nrec->type) {
4241 case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
4242 /* exclusions do not conflict by definition */
4243 break;
4245 case FOREST_TRUST_TOP_LEVEL_NAME:
4246 dns_name = nrec->data.name.string;
4247 dns_len = nrec->data.name.size;
4248 break;
4250 case LSA_FOREST_TRUST_DOMAIN_INFO:
4251 dns_name = nrec->data.info.dns_name.string;
4252 dns_len = nrec->data.info.dns_name.size;
4253 nb_name = nrec->data.info.netbios_name.string;
4254 sid = &nrec->data.info.sid;
4255 break;
4258 if (!dns_name) continue;
4260 /* check if this is already taken and not excluded */
4261 for (i = 0; i < tdo_fti->count; i++) {
4262 trec = &tdo_fti->records[i].record;
4264 switch (trec->type) {
4265 case FOREST_TRUST_TOP_LEVEL_NAME:
4266 ex_rule = false;
4267 tname = trec->data.name.string;
4268 tlen = trec->data.name.size;
4269 break;
4270 case FOREST_TRUST_TOP_LEVEL_NAME_EX:
4271 ex_rule = true;
4272 tname = trec->data.name.string;
4273 tlen = trec->data.name.size;
4274 break;
4275 case FOREST_TRUST_DOMAIN_INFO:
4276 ex_rule = false;
4277 tname = trec->data.info.dns_name.string;
4278 tlen = trec->data.info.dns_name.size;
4280 ret = dns_cmp(dns_name, dns_len, tname, tlen);
4281 switch (ret) {
4282 case DNS_CMP_MATCH:
4283 /* if it matches exclusion,
4284 * it doesn't conflict */
4285 if (ex_rule) {
4286 exclusion = true;
4287 break;
4289 /* fall through */
4290 case DNS_CMP_FIRST_IS_CHILD:
4291 case DNS_CMP_SECOND_IS_CHILD:
4292 tln_conflict = true;
4293 /* fall through */
4294 default:
4295 break;
4298 /* explicit exclusion, no dns name conflict here */
4299 if (exclusion) {
4300 tln_conflict = false;
4303 if (trec->type != FOREST_TRUST_DOMAIN_INFO) {
4304 continue;
4307 /* also test for domain info */
4308 if (!(trec->flags & LSA_SID_DISABLED_ADMIN) &&
4309 dom_sid_compare(&trec->data.info.sid, sid) == 0) {
4310 sid_conflict = true;
4312 if (!(trec->flags & LSA_NB_DISABLED_ADMIN) &&
4313 (nb_name != NULL) &&
4314 strcasecmp_m(trec->data.info.netbios_name.string,
4315 nb_name) == 0) {
4316 nb_conflict = true;
4320 if (tln_conflict) {
4321 nt_status = add_collision(c_info, new_fti_idx,
4322 collision_type,
4323 LSA_TLN_DISABLED_CONFLICT,
4324 tdo_name);
4325 if (!NT_STATUS_IS_OK(nt_status)) {
4326 goto done;
4329 if (sid_conflict) {
4330 nt_status = add_collision(c_info, new_fti_idx,
4331 collision_type,
4332 LSA_SID_DISABLED_CONFLICT,
4333 tdo_name);
4334 if (!NT_STATUS_IS_OK(nt_status)) {
4335 goto done;
4338 if (nb_conflict) {
4339 nt_status = add_collision(c_info, new_fti_idx,
4340 collision_type,
4341 LSA_NB_DISABLED_CONFLICT,
4342 tdo_name);
4343 if (!NT_STATUS_IS_OK(nt_status)) {
4344 goto done;
4349 done:
4350 return nt_status;
4353 static NTSTATUS add_collision(struct lsa_ForestTrustCollisionInfo *c_info,
4354 uint32_t idx, uint32_t collision_type,
4355 uint32_t conflict_type, const char *tdo_name)
4357 struct lsa_ForestTrustCollisionRecord **es;
4358 uint32_t i = c_info->count;
4360 es = talloc_realloc(c_info, c_info->entries,
4361 struct lsa_ForestTrustCollisionRecord *, i + 1);
4362 if (!es) {
4363 return NT_STATUS_NO_MEMORY;
4365 c_info->entries = es;
4366 c_info->count = i + 1;
4368 es[i] = talloc(es, struct lsa_ForestTrustCollisionRecord);
4369 if (!es[i]) {
4370 return NT_STATUS_NO_MEMORY;
4373 es[i]->index = idx;
4374 es[i]->type = collision_type;
4375 es[i]->flags.flags = conflict_type;
4376 es[i]->name.string = talloc_strdup(es[i], tdo_name);
4377 if (!es[i]->name.string) {
4378 return NT_STATUS_NO_MEMORY;
4380 es[i]->name.size = strlen(es[i]->name.string);
4382 return NT_STATUS_OK;
4386 lsa_lsaRSetForestTrustInformation
4388 static NTSTATUS dcesrv_lsa_lsaRSetForestTrustInformation(struct dcesrv_call_state *dce_call,
4389 TALLOC_CTX *mem_ctx,
4390 struct lsa_lsaRSetForestTrustInformation *r)
4392 struct dcesrv_handle *h;
4393 struct lsa_policy_state *p_state;
4394 const char *trust_attrs[] = { "trustPartner", "trustAttributes",
4395 "msDS-TrustForestTrustInfo", NULL };
4396 struct ldb_message **dom_res = NULL;
4397 struct ldb_dn *tdo_dn;
4398 struct ldb_message *msg;
4399 int num_res, i;
4400 const char *td_name;
4401 uint32_t trust_attributes;
4402 struct lsa_ForestTrustCollisionInfo *c_info;
4403 struct ForestTrustInfo *nfti;
4404 struct ForestTrustInfo *fti;
4405 DATA_BLOB ft_blob;
4406 enum ndr_err_code ndr_err;
4407 NTSTATUS nt_status;
4408 bool am_rodc;
4409 int ret;
4411 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
4413 p_state = h->data;
4415 if (strcmp(p_state->domain_dns, p_state->forest_dns)) {
4416 return NT_STATUS_INVALID_DOMAIN_STATE;
4419 /* abort if we are not a PDC */
4420 if (!samdb_is_pdc(p_state->sam_ldb)) {
4421 return NT_STATUS_INVALID_DOMAIN_ROLE;
4424 ret = samdb_rodc(p_state->sam_ldb, &am_rodc);
4425 if (ret == LDB_SUCCESS && am_rodc) {
4426 return NT_STATUS_NO_SUCH_DOMAIN;
4429 /* check caller has TRUSTED_SET_AUTH */
4431 /* fetch all trusted domain objects */
4432 num_res = gendb_search(p_state->sam_ldb, mem_ctx,
4433 p_state->system_dn,
4434 &dom_res, trust_attrs,
4435 "(objectclass=trustedDomain)");
4436 if (num_res == 0) {
4437 return NT_STATUS_NO_SUCH_DOMAIN;
4440 for (i = 0; i < num_res; i++) {
4441 td_name = ldb_msg_find_attr_as_string(dom_res[i],
4442 "trustPartner", NULL);
4443 if (!td_name) {
4444 return NT_STATUS_INVALID_DOMAIN_STATE;
4446 if (strcasecmp_m(td_name,
4447 r->in.trusted_domain_name->string) == 0) {
4448 break;
4451 if (i >= num_res) {
4452 return NT_STATUS_NO_SUCH_DOMAIN;
4455 tdo_dn = dom_res[i]->dn;
4457 trust_attributes = ldb_msg_find_attr_as_uint(dom_res[i],
4458 "trustAttributes", 0);
4459 if (!(trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
4460 return NT_STATUS_INVALID_PARAMETER;
4463 if (r->in.highest_record_type >= LSA_FOREST_TRUST_RECORD_TYPE_LAST) {
4464 return NT_STATUS_INVALID_PARAMETER;
4467 nfti = talloc(mem_ctx, struct ForestTrustInfo);
4468 if (!nfti) {
4469 return NT_STATUS_NO_MEMORY;
4472 nt_status = make_ft_info(nfti, r->in.forest_trust_info, nfti);
4473 if (!NT_STATUS_IS_OK(nt_status)) {
4474 return nt_status;
4477 c_info = talloc_zero(r->out.collision_info,
4478 struct lsa_ForestTrustCollisionInfo);
4479 if (!c_info) {
4480 return NT_STATUS_NO_MEMORY;
4483 /* first check own info, then other domains */
4484 fti = talloc(mem_ctx, struct ForestTrustInfo);
4485 if (!fti) {
4486 return NT_STATUS_NO_MEMORY;
4489 nt_status = own_ft_info(p_state, fti);
4490 if (!NT_STATUS_IS_OK(nt_status)) {
4491 return nt_status;
4494 nt_status = check_ft_info(c_info, p_state->domain_dns,
4495 fti, nfti, c_info);
4496 if (!NT_STATUS_IS_OK(nt_status)) {
4497 return nt_status;
4500 for (i = 0; i < num_res; i++) {
4501 fti = talloc(mem_ctx, struct ForestTrustInfo);
4502 if (!fti) {
4503 return NT_STATUS_NO_MEMORY;
4506 nt_status = get_ft_info(mem_ctx, dom_res[i], fti);
4507 if (!NT_STATUS_IS_OK(nt_status)) {
4508 if (NT_STATUS_EQUAL(nt_status,
4509 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4510 continue;
4512 return nt_status;
4515 td_name = ldb_msg_find_attr_as_string(dom_res[i],
4516 "trustPartner", NULL);
4517 if (!td_name) {
4518 return NT_STATUS_INVALID_DOMAIN_STATE;
4521 nt_status = check_ft_info(c_info, td_name, fti, nfti, c_info);
4522 if (!NT_STATUS_IS_OK(nt_status)) {
4523 return nt_status;
4527 *r->out.collision_info = c_info;
4529 if (r->in.check_only != 0) {
4530 return NT_STATUS_OK;
4533 /* not just a check, write info back */
4535 ndr_err = ndr_push_struct_blob(&ft_blob, mem_ctx, nfti,
4536 (ndr_push_flags_fn_t)ndr_push_ForestTrustInfo);
4537 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
4538 return NT_STATUS_INVALID_PARAMETER;
4541 msg = ldb_msg_new(mem_ctx);
4542 if (msg == NULL) {
4543 return NT_STATUS_NO_MEMORY;
4546 msg->dn = ldb_dn_copy(mem_ctx, tdo_dn);
4547 if (!msg->dn) {
4548 return NT_STATUS_NO_MEMORY;
4551 ret = ldb_msg_add_empty(msg, "msDS-TrustForestTrustInfo",
4552 LDB_FLAG_MOD_REPLACE, NULL);
4553 if (ret != LDB_SUCCESS) {
4554 return NT_STATUS_NO_MEMORY;
4556 ret = ldb_msg_add_value(msg, "msDS-TrustForestTrustInfo",
4557 &ft_blob, NULL);
4558 if (ret != LDB_SUCCESS) {
4559 return NT_STATUS_NO_MEMORY;
4562 ret = ldb_modify(p_state->sam_ldb, msg);
4563 if (ret != LDB_SUCCESS) {
4564 DEBUG(0, ("Failed to store Forest Trust Info: %s\n",
4565 ldb_errstring(p_state->sam_ldb)));
4567 switch (ret) {
4568 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
4569 return NT_STATUS_ACCESS_DENIED;
4570 default:
4571 return NT_STATUS_INTERNAL_DB_CORRUPTION;
4575 return NT_STATUS_OK;
4579 lsa_CREDRRENAME
4581 static NTSTATUS dcesrv_lsa_CREDRRENAME(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4582 struct lsa_CREDRRENAME *r)
4584 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4590 lsa_LSAROPENPOLICYSCE
4592 static NTSTATUS dcesrv_lsa_LSAROPENPOLICYSCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4593 struct lsa_LSAROPENPOLICYSCE *r)
4595 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4600 lsa_LSARADTREGISTERSECURITYEVENTSOURCE
4602 static NTSTATUS dcesrv_lsa_LSARADTREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4603 struct lsa_LSARADTREGISTERSECURITYEVENTSOURCE *r)
4605 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4610 lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE
4612 static NTSTATUS dcesrv_lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4613 struct lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE *r)
4615 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4620 lsa_LSARADTREPORTSECURITYEVENT
4622 static NTSTATUS dcesrv_lsa_LSARADTREPORTSECURITYEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4623 struct lsa_LSARADTREPORTSECURITYEVENT *r)
4625 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4629 /* include the generated boilerplate */
4630 #include "librpc/gen_ndr/ndr_lsa_s.c"
4634 /*****************************************
4635 NOTE! The remaining calls below were
4636 removed in w2k3, so the DCESRV_FAULT()
4637 replies are the correct implementation. Do
4638 not try and fill these in with anything else
4639 ******************************************/
4642 dssetup_DsRoleDnsNameToFlatName
4644 static WERROR dcesrv_dssetup_DsRoleDnsNameToFlatName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4645 struct dssetup_DsRoleDnsNameToFlatName *r)
4647 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4652 dssetup_DsRoleDcAsDc
4654 static WERROR dcesrv_dssetup_DsRoleDcAsDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4655 struct dssetup_DsRoleDcAsDc *r)
4657 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4662 dssetup_DsRoleDcAsReplica
4664 static WERROR dcesrv_dssetup_DsRoleDcAsReplica(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4665 struct dssetup_DsRoleDcAsReplica *r)
4667 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4672 dssetup_DsRoleDemoteDc
4674 static WERROR dcesrv_dssetup_DsRoleDemoteDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4675 struct dssetup_DsRoleDemoteDc *r)
4677 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4682 dssetup_DsRoleGetDcOperationProgress
4684 static WERROR dcesrv_dssetup_DsRoleGetDcOperationProgress(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4685 struct dssetup_DsRoleGetDcOperationProgress *r)
4687 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4692 dssetup_DsRoleGetDcOperationResults
4694 static WERROR dcesrv_dssetup_DsRoleGetDcOperationResults(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4695 struct dssetup_DsRoleGetDcOperationResults *r)
4697 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4702 dssetup_DsRoleCancel
4704 static WERROR dcesrv_dssetup_DsRoleCancel(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4705 struct dssetup_DsRoleCancel *r)
4707 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4712 dssetup_DsRoleServerSaveStateForUpgrade
4714 static WERROR dcesrv_dssetup_DsRoleServerSaveStateForUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4715 struct dssetup_DsRoleServerSaveStateForUpgrade *r)
4717 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4722 dssetup_DsRoleUpgradeDownlevelServer
4724 static WERROR dcesrv_dssetup_DsRoleUpgradeDownlevelServer(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4725 struct dssetup_DsRoleUpgradeDownlevelServer *r)
4727 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4732 dssetup_DsRoleAbortDownlevelServerUpgrade
4734 static WERROR dcesrv_dssetup_DsRoleAbortDownlevelServerUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4735 struct dssetup_DsRoleAbortDownlevelServerUpgrade *r)
4737 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4741 /* include the generated boilerplate */
4742 #include "librpc/gen_ndr/ndr_dssetup_s.c"
4744 NTSTATUS dcerpc_server_lsa_init(void)
4746 NTSTATUS ret;
4748 ret = dcerpc_server_dssetup_init();
4749 if (!NT_STATUS_IS_OK(ret)) {
4750 return ret;
4752 ret = dcerpc_server_lsarpc_init();
4753 if (!NT_STATUS_IS_OK(ret)) {
4754 return ret;
4756 return ret;