]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
s4:rpc_server: Implement dcesrv_lsa_CreateTrustedDomain_common()
authorAndreas Schneider <asn@samba.org>
Wed, 20 Dec 2023 17:56:14 +0000 (18:56 +0100)
committerAndrew Bartlett <abartlet@samba.org>
Tue, 9 Apr 2024 22:52:38 +0000 (22:52 +0000)
Signed-off-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
source4/rpc_server/lsa/dcesrv_lsa.c

index f793b24f59e3fef952e15d946367107f23d2b459..220f2a5442c92f0b68c7f90c787ec21c07069da7 100644 (file)
@@ -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
 */