From: Andreas Schneider Date: Wed, 20 Dec 2023 17:56:14 +0000 (+0100) Subject: s4:rpc_server: Implement dcesrv_lsa_CreateTrustedDomain_common() X-Git-Tag: tdb-1.4.11~1249 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=6d90397ff28a8dc924292f3593d970e7bf5e57ab;p=thirdparty%2Fsamba.git s4:rpc_server: Implement dcesrv_lsa_CreateTrustedDomain_common() Signed-off-by: Andreas Schneider Reviewed-by: Andrew Bartlett --- diff --git a/source4/rpc_server/lsa/dcesrv_lsa.c b/source4/rpc_server/lsa/dcesrv_lsa.c index f793b24f59e..220f2a5442c 100644 --- a/source4/rpc_server/lsa/dcesrv_lsa.c +++ b/source4/rpc_server/lsa/dcesrv_lsa.c @@ -1149,6 +1149,285 @@ static NTSTATUS dcesrv_lsa_CreateTrustedDomain_precheck( return NT_STATUS_OK; } +static NTSTATUS dcesrv_lsa_CreateTrustedDomain_common(struct dcesrv_call_state *dce_call, + TALLOC_CTX *mem_ctx, + struct dcesrv_handle *policy_handle, + uint32_t access_mask, + struct lsa_TrustDomainInfoInfoEx *info, + struct trustDomainPasswords *auth_struct, + struct policy_handle **ptrustdom_handle) +{ + struct lsa_policy_state *policy_state = policy_handle->data; + struct ldb_context *sam_ldb = policy_state->sam_ldb; + struct lsa_trusted_domain_state *trusted_domain_state = NULL; + struct ldb_message **msgs, *msg; + const char *attrs[] = { + NULL + }; + const char *netbios_name = info->netbios_name.string; + const char *dns_name = info->domain_name.string; + DATA_BLOB trustAuthIncoming = data_blob_null; + DATA_BLOB trustAuthOutgoing = data_blob_null; + struct dcesrv_handle *handle = NULL; + struct server_id *server_ids = NULL; + uint32_t num_server_ids = 0; + char *dns_encoded = NULL; + char *netbios_encoded = NULL; + char *sid_encoded = NULL; + struct imessaging_context *imsg_ctx = + dcesrv_imessaging_context(dce_call->conn); + NTSTATUS status; + bool ok; + int ret; + + if (auth_struct->incoming.count) { + status = get_trustauth_inout_blob(dce_call, + mem_ctx, + &auth_struct->incoming, + &trustAuthIncoming); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + } + + if (auth_struct->outgoing.count) { + status = get_trustauth_inout_blob(dce_call, + mem_ctx, + &auth_struct->outgoing, + &trustAuthOutgoing); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + } + + dns_encoded = ldb_binary_encode_string(mem_ctx, dns_name); + if (dns_encoded == NULL) { + return NT_STATUS_NO_MEMORY; + } + netbios_encoded = ldb_binary_encode_string(mem_ctx, netbios_name); + if (netbios_encoded == NULL) { + return NT_STATUS_NO_MEMORY; + } + sid_encoded = ldap_encode_ndr_dom_sid(mem_ctx, info->sid); + if (sid_encoded == NULL) { + return NT_STATUS_NO_MEMORY; + } + + trusted_domain_state = talloc_zero(mem_ctx, + struct lsa_trusted_domain_state); + if (trusted_domain_state == NULL) { + return NT_STATUS_NO_MEMORY; + } + trusted_domain_state->policy = policy_state; + + ret = ldb_transaction_start(sam_ldb); + if (ret != LDB_SUCCESS) { + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } + + /* search for the trusted_domain record */ + ret = gendb_search(sam_ldb, + mem_ctx, + policy_state->system_dn, + &msgs, + attrs, + "(&(objectClass=trustedDomain)(|" + "(flatname=%s)(trustPartner=%s)" + "(flatname=%s)(trustPartner=%s)" + "(securityIdentifier=%s)))", + dns_encoded, + dns_encoded, + netbios_encoded, + netbios_encoded, + sid_encoded); + if (ret > 0) { + ldb_transaction_cancel(sam_ldb); + return NT_STATUS_OBJECT_NAME_COLLISION; + } + if (ret < 0) { + ldb_transaction_cancel(sam_ldb); + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } + + msg = ldb_msg_new(mem_ctx); + if (msg == NULL) { + return NT_STATUS_NO_MEMORY; + } + + msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn); + if (msg->dn == NULL) { + ldb_transaction_cancel(sam_ldb); + return NT_STATUS_NO_MEMORY; + } + + ok = ldb_dn_add_child_fmt(msg->dn, "cn=%s", dns_name); + if (!ok) { + ldb_transaction_cancel(sam_ldb); + return NT_STATUS_NO_MEMORY; + } + + ret = ldb_msg_add_string(msg, "objectClass", "trustedDomain"); + if (ret != LDB_SUCCESS) { + ldb_transaction_cancel(sam_ldb); + return NT_STATUS_NO_MEMORY;; + } + + ret = ldb_msg_add_string(msg, "flatname", netbios_name); + if (ret != LDB_SUCCESS) { + ldb_transaction_cancel(sam_ldb); + return NT_STATUS_NO_MEMORY; + } + + ret = ldb_msg_add_string(msg, "trustPartner", dns_name); + if (ret != LDB_SUCCESS) { + ldb_transaction_cancel(sam_ldb); + return NT_STATUS_NO_MEMORY;; + } + + ret = samdb_msg_add_dom_sid( + sam_ldb, mem_ctx, msg, "securityIdentifier", info->sid); + if (ret != LDB_SUCCESS) { + ldb_transaction_cancel(sam_ldb); + return NT_STATUS_NO_MEMORY;; + } + + ret = samdb_msg_add_int( + sam_ldb, mem_ctx, msg, "trustType", info->trust_type); + if (ret != LDB_SUCCESS) { + ldb_transaction_cancel(sam_ldb); + return NT_STATUS_NO_MEMORY;; + } + + ret = samdb_msg_add_int(sam_ldb, + mem_ctx, + msg, + "trustAttributes", + info->trust_attributes); + if (ret != LDB_SUCCESS) { + ldb_transaction_cancel(sam_ldb); + return NT_STATUS_NO_MEMORY;; + } + + ret = samdb_msg_add_int(sam_ldb, + mem_ctx, + msg, + "trustDirection", + info->trust_direction); + if (ret != LDB_SUCCESS) { + ldb_transaction_cancel(sam_ldb); + return NT_STATUS_NO_MEMORY;; + } + + if (trustAuthIncoming.length > 0) { + ret = ldb_msg_add_value(msg, + "trustAuthIncoming", + &trustAuthIncoming, + NULL); + if (ret != LDB_SUCCESS) { + ldb_transaction_cancel(sam_ldb); + return NT_STATUS_NO_MEMORY; + } + } + if (trustAuthOutgoing.length > 0) { + ret = ldb_msg_add_value(msg, + "trustAuthOutgoing", + &trustAuthOutgoing, + NULL); + if (ret != LDB_SUCCESS) { + ldb_transaction_cancel(sam_ldb); + return NT_STATUS_NO_MEMORY; + } + } + + trusted_domain_state->trusted_domain_dn = ldb_dn_copy( + trusted_domain_state, msg->dn); + + /* create the trusted_domain */ + ret = ldb_add(sam_ldb, msg); + switch (ret) { + case LDB_SUCCESS: + break; + case LDB_ERR_ENTRY_ALREADY_EXISTS: + ldb_transaction_cancel(sam_ldb); + DEBUG(0,("Failed to create trusted domain record %s: %s\n", + ldb_dn_get_linearized(msg->dn), + ldb_errstring(sam_ldb))); + return NT_STATUS_DOMAIN_EXISTS; + case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS: + ldb_transaction_cancel(sam_ldb); + DEBUG(0,("Failed to create trusted domain record %s: %s\n", + ldb_dn_get_linearized(msg->dn), + ldb_errstring(sam_ldb))); + return NT_STATUS_ACCESS_DENIED; + default: + ldb_transaction_cancel(sam_ldb); + DEBUG(0,("Failed to create user record %s: %s\n", + ldb_dn_get_linearized(msg->dn), + ldb_errstring(sam_ldb))); + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } + + if (info->trust_direction & LSA_TRUST_DIRECTION_INBOUND) { + struct ldb_dn *user_dn; + /* Inbound trusts must also create a cn=users object to match */ + status = add_trust_user(mem_ctx, sam_ldb, + policy_state->domain_dn, + netbios_name, + &auth_struct->incoming, + &user_dn); + if (!NT_STATUS_IS_OK(status)) { + ldb_transaction_cancel(sam_ldb); + return status; + } + + /* save the trust user dn */ + trusted_domain_state->trusted_domain_user_dn + = talloc_steal(trusted_domain_state, user_dn); + } + + ret = ldb_transaction_commit(sam_ldb); + if (ret != LDB_SUCCESS) { + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } + + /* + * Notify winbindd that we have a new trust + */ + status = irpc_servers_byname(imsg_ctx, + mem_ctx, + "winbind_server", + &num_server_ids, + &server_ids); + if (NT_STATUS_IS_OK(status) && num_server_ids >= 1) { + imessaging_send(imsg_ctx, + server_ids[0], + MSG_WINBIND_RELOAD_TRUSTED_DOMAINS, + NULL); + } + TALLOC_FREE(server_ids); + + handle = dcesrv_handle_create(dce_call, LSA_HANDLE_TRUSTED_DOMAIN); + if (handle == NULL) { + return NT_STATUS_NO_MEMORY; + } + + handle->data = talloc_steal(handle, trusted_domain_state); + + trusted_domain_state->access_mask = access_mask; + + /* FIXME don't use talloc_reference */ + trusted_domain_state->policy = talloc_reference(trusted_domain_state, + policy_state); + NT_STATUS_HAVE_NO_MEMORY(trusted_domain_state->policy); + + *ptrustdom_handle = talloc_zero(mem_ctx, struct policy_handle); + NT_STATUS_HAVE_NO_MEMORY(*ptrustdom_handle); + + **ptrustdom_handle = handle->wire_handle; + + return NT_STATUS_OK; +} + /* lsa_CreateTrustedDomainEx2 */