]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
s4:kdc: Implement samba_kdc_check_s4u2proxy_rbcd()
authorAndreas Schneider <asn@samba.org>
Tue, 14 Dec 2021 10:16:12 +0000 (11:16 +0100)
committerAndreas Schneider <asn@cryptomilk.org>
Fri, 4 Mar 2022 14:05:31 +0000 (14:05 +0000)
This will be used by the MIT KDB plugin in the next commits.

A security descriptor created by Windows looks like this:

    security_descriptor: struct security_descriptor
        revision                 : SECURITY_DESCRIPTOR_REVISION_1 (1)
        type                     : 0x8004 (32772)
               0: SEC_DESC_OWNER_DEFAULTED
               0: SEC_DESC_GROUP_DEFAULTED
               1: SEC_DESC_DACL_PRESENT
               0: SEC_DESC_DACL_DEFAULTED
               0: SEC_DESC_SACL_PRESENT
               0: SEC_DESC_SACL_DEFAULTED
               0: SEC_DESC_DACL_TRUSTED
               0: SEC_DESC_SERVER_SECURITY
               0: SEC_DESC_DACL_AUTO_INHERIT_REQ
               0: SEC_DESC_SACL_AUTO_INHERIT_REQ
               0: SEC_DESC_DACL_AUTO_INHERITED
               0: SEC_DESC_SACL_AUTO_INHERITED
               0: SEC_DESC_DACL_PROTECTED
               0: SEC_DESC_SACL_PROTECTED
               0: SEC_DESC_RM_CONTROL_VALID
               1: SEC_DESC_SELF_RELATIVE
        owner_sid                : *
            owner_sid                : S-1-5-32-544
        group_sid                : NULL
        sacl                     : NULL
        dacl                     : *
            dacl: struct security_acl
                revision                 : SECURITY_ACL_REVISION_ADS (4)
                size                     : 0x002c (44)
                num_aces                 : 0x00000001 (1)
                aces: ARRAY(1)
                    aces: struct security_ace
                        type                     : SEC_ACE_TYPE_ACCESS_ALLOWED (0)
                        flags                    : 0x00 (0)
                               0: SEC_ACE_FLAG_OBJECT_INHERIT
                               0: SEC_ACE_FLAG_CONTAINER_INHERIT
                               0: SEC_ACE_FLAG_NO_PROPAGATE_INHERIT
                               0: SEC_ACE_FLAG_INHERIT_ONLY
                               0: SEC_ACE_FLAG_INHERITED_ACE
                            0x00: SEC_ACE_FLAG_VALID_INHERIT (0)
                               0: SEC_ACE_FLAG_SUCCESSFUL_ACCESS
                               0: SEC_ACE_FLAG_FAILED_ACCESS
                        size                     : 0x0024 (36)
                        access_mask              : 0x000f01ff (983551)
                        object                   : union security_ace_object_ctr(case 0)
                        trustee                  : S-1-5-21-3001743926-1909451141-602466370-1108

Created with the following powershell code:

    $host1 = Get-ADComputer -Identity ServerA
    $host2 = Get-ADComputer -Identity ServerB
    Set-ADComputer $host2 -PrincipalsAllowedToDelegateToAccount $host1

Signed-off-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Stefan Metzmacher <metze@samba.org>
source4/kdc/db-glue.c
source4/kdc/db-glue.h

index d280aa02902dd1671490a519f3d54f0103026b3e..bea9ac8e1ae5b64b15ed6d74d23e77445a05de57 100644 (file)
@@ -23,6 +23,7 @@
 
 #include "includes.h"
 #include "libcli/security/security.h"
+#include "librpc/gen_ndr/ndr_security.h"
 #include "auth/auth.h"
 #include "auth/auth_sam.h"
 #include "dsdb/samdb/samdb.h"
@@ -2823,6 +2824,175 @@ bad_option:
        return KRB5KDC_ERR_BADOPTION;
 }
 
+/*
+ * This method is called for S4U2Proxy requests and implements the
+ * resource-based constrained delegation variant, which can support
+ * cross-realm delegation.
+ */
+krb5_error_code samba_kdc_check_s4u2proxy_rbcd(
+               krb5_context context,
+               struct samba_kdc_db_context *kdc_db_ctx,
+               krb5_const_principal client_principal,
+               krb5_const_principal server_principal,
+               krb5_pac header_pac,
+               struct samba_kdc_entry *proxy_skdc_entry)
+{
+       krb5_error_code code;
+       enum ndr_err_code ndr_err;
+       char *client_name = NULL;
+       char *server_name = NULL;
+       const char *proxy_dn = NULL;
+       const DATA_BLOB *data = NULL;
+       struct security_descriptor *rbcd_security_descriptor = NULL;
+       struct auth_user_info_dc *user_info_dc = NULL;
+       struct auth_session_info *session_info = NULL;
+       uint32_t session_info_flags = AUTH_SESSION_INFO_SIMPLE_PRIVILEGES;
+       uint32_t access_desired = SEC_ADS_GENERIC_ALL; /* => 0x000f01ff */
+       uint32_t access_granted = 0;
+       NTSTATUS nt_status;
+       TALLOC_CTX *mem_ctx = NULL;
+
+       mem_ctx = talloc_named(kdc_db_ctx,
+                              0,
+                              "samba_kdc_check_s4u2proxy_rbcd");
+       if (mem_ctx == NULL) {
+               errno = ENOMEM;
+               code = errno;
+
+               return code;
+       }
+
+       proxy_dn = ldb_dn_get_linearized(proxy_skdc_entry->msg->dn);
+       if (proxy_dn == NULL) {
+               DBG_ERR("ldb_dn_get_linearized failed for proxy_dn!\n");
+               TALLOC_FREE(mem_ctx);
+               if (errno == 0) {
+                       errno = ENOMEM;
+               }
+               code = errno;
+
+               goto out;
+       }
+
+       rbcd_security_descriptor = talloc_zero(mem_ctx,
+                                              struct security_descriptor);
+       if (rbcd_security_descriptor == NULL) {
+               errno = ENOMEM;
+               code = errno;
+
+               goto out;
+       }
+
+       code = krb5_unparse_name_flags(context,
+                                      client_principal,
+                                      KRB5_PRINCIPAL_UNPARSE_DISPLAY,
+                                      &client_name);
+       if (code != 0) {
+               DBG_ERR("Unable to parse client_principal!\n");
+               goto out;
+       }
+
+       code = krb5_unparse_name_flags(context,
+                                      server_principal,
+                                      KRB5_PRINCIPAL_UNPARSE_DISPLAY,
+                                      &server_name);
+       if (code != 0) {
+               DBG_ERR("Unable to parse server_principal!\n");
+               SAFE_FREE(client_name);
+               goto out;
+       }
+
+       DBG_INFO("Check delegation from client[%s] to server[%s] via "
+                "proxy[%s]\n",
+                client_name,
+                server_name,
+                proxy_dn);
+
+       code = kerberos_pac_to_user_info_dc(mem_ctx,
+                                           header_pac,
+                                           context,
+                                           &user_info_dc,
+                                           NULL,
+                                           NULL);
+       if (code != 0) {
+               goto out;
+       }
+
+       if (user_info_dc->info->authenticated) {
+               session_info_flags |= AUTH_SESSION_INFO_AUTHENTICATED;
+       }
+
+       nt_status = auth_generate_session_info(mem_ctx,
+                                              kdc_db_ctx->lp_ctx,
+                                              kdc_db_ctx->samdb,
+                                              user_info_dc,
+                                              session_info_flags,
+                                              &session_info);
+       if (!NT_STATUS_IS_OK(nt_status)) {
+               code = map_errno_from_nt_status(nt_status);
+               goto out;
+       }
+
+       data = ldb_msg_find_ldb_val(proxy_skdc_entry->msg,
+                                   "msDS-AllowedToActOnBehalfOfOtherIdentity");
+       if (data == NULL) {
+               DBG_ERR("Could not find security descriptor"
+                       "msDS-AllowedToActOnBehalfOfOtherIdentity in "
+                       "proxy[%s]\n",
+                       proxy_dn);
+               code = KRB5KDC_ERR_BADOPTION;
+               goto out;
+       }
+
+       ndr_err = ndr_pull_struct_blob(
+                       data,
+                       mem_ctx,
+                       rbcd_security_descriptor,
+                       (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
+       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+               errno = ndr_map_error2errno(ndr_err);
+               DBG_ERR("Failed to unmarshall "
+                       "msDS-AllowedToActOnBehalfOfOtherIdentity "
+                       "security descriptor of proxy[%s]\n",
+                       proxy_dn);
+               code = KRB5KDC_ERR_BADOPTION;
+               goto out;
+       }
+
+       if (DEBUGLEVEL >= 10) {
+               NDR_PRINT_DEBUG(security_token, session_info->security_token);
+               NDR_PRINT_DEBUG(security_descriptor, rbcd_security_descriptor);
+       }
+
+       nt_status = sec_access_check_ds(rbcd_security_descriptor,
+                                       session_info->security_token,
+                                       access_desired,
+                                       &access_granted,
+                                       NULL,
+                                       NULL);
+
+       if (!NT_STATUS_IS_OK(nt_status)) {
+               DBG_WARNING("RBCD: sec_access_check_ds(access_desired=%#08x, "
+                           "access_granted:%#08x) failed with: %s\n",
+                           access_desired,
+                           access_granted,
+                           nt_errstr(nt_status));
+
+               code = KRB5KDC_ERR_BADOPTION;
+               goto out;
+       }
+
+       DBG_NOTICE("RBCD: Access granted for client[%s]\n", client_name);
+
+       code = 0;
+out:
+       SAFE_FREE(client_name);
+       SAFE_FREE(server_name);
+
+       TALLOC_FREE(mem_ctx);
+       return code;
+}
+
 NTSTATUS samba_kdc_setup_db_ctx(TALLOC_CTX *mem_ctx, struct samba_kdc_base_context *base_ctx,
                                struct samba_kdc_db_context **kdc_db_ctx_out)
 {
@@ -2969,4 +3139,4 @@ NTSTATUS samba_kdc_setup_db_ctx(TALLOC_CTX *mem_ctx, struct samba_kdc_base_conte
        }
        *kdc_db_ctx_out = kdc_db_ctx;
        return NT_STATUS_OK;
-}
+}
\ No newline at end of file
index 218bd3cfae2e27e1f9ed66d4e6d997a9514e2728..f3d9c817b77dd18f80850c00bba227ffc04f5ab3 100644 (file)
@@ -61,5 +61,13 @@ samba_kdc_check_s4u2proxy(krb5_context context,
                          struct samba_kdc_entry *skdc_entry,
                          krb5_const_principal target_principal);
 
+krb5_error_code samba_kdc_check_s4u2proxy_rbcd(
+               krb5_context context,
+               struct samba_kdc_db_context *kdc_db_ctx,
+               krb5_const_principal client_principal,
+               krb5_const_principal server_principal,
+               krb5_pac header_pac,
+               struct samba_kdc_entry *proxy_skdc_entry);
+
 NTSTATUS samba_kdc_setup_db_ctx(TALLOC_CTX *mem_ctx, struct samba_kdc_base_context *base_ctx,
                                struct samba_kdc_db_context **kdc_db_ctx_out);