CVE-2022-2031 s4:kdc: Add MIT support for ATTRIBUTES_INFO and REQUESTER_SID PAC buffers
authorJoseph Sutton <josephsutton@catalyst.net.nz>
Wed, 15 Jun 2022 07:37:39 +0000 (19:37 +1200)
committerJule Anger <janger@samba.org>
Sun, 24 Jul 2022 09:42:01 +0000 (11:42 +0200)
So that we do not confuse TGTs and kpasswd tickets, it is critical to
check that the REQUESTER_SID buffer exists in TGTs, and to ensure that
it is not propagated to service tickets.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047

Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
[jsutton@samba.org Brought in changes to add ATTRIBUTES_INFO and
 REQUESTER_SID buffers to new PACs, and updated knownfails]

[jsutton@samba.org Adjusted MIT knownfails]

selftest/knownfail_mit_kdc
source4/kdc/mit-kdb/kdb_samba_policies.c
source4/kdc/mit_samba.c
source4/kdc/mit_samba.h

index 4d685af7140c5ca70e6d7b6f84719732de3dcaa2..108c6055d0cf073955ba7687cbc4e9d125d55502 100644 (file)
@@ -445,7 +445,6 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_nonexisting
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_authdata_no_pac
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_no_pac
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_pac_request_none
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_pac_request_true
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_req
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_allowed_denied
@@ -482,7 +481,6 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_no_pac
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rename
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_req_invalid
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_req_no_requester_sid
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_allowed_denied
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_denied
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_no_krbtgt_link
@@ -518,7 +516,6 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_wrong_srealm
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_authdata_no_pac
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_no_pac
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_pac_request_none
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_pac_request_true
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_req
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_allowed_denied
@@ -536,21 +533,17 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_
 #
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_false
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_missing_renew_false
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_missing_renew_none
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_missing_renew_true
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_missing_rodc_renew_false
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_missing_rodc_renew_none
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_missing_rodc_renew_true
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_none
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_renew_false
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_renew_none
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_renew_true
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_rodc_renew_false
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_rodc_renew_none
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_rodc_renew_true
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_true
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_pac_attrs_false
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_pac_attrs_none
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_pac_attrs_true
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_req_from_rodc_no_pac_attrs
 #
@@ -571,21 +564,11 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_
 #
 # PAC requester SID tests
 #
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_as_requester_sid
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_logon_info_sid_mismatch_existing
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_logon_info_sid_mismatch_nonexisting
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_requester_sid_mismatch_existing
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_requester_sid_mismatch_nonexisting
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_req_from_rodc_no_requester_sid
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_renew
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_rodc_renew
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_rodc_validate
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_validate
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_renew
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_rodc_renew
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_rodc_validate
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_validate
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_logon_info_only_sid_mismatch_existing
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_logon_info_only_sid_mismatch_nonexisting
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_logon_info_sid_mismatch_existing
index 7bc9a7b3347cbc7a88f604fa73456380aacf0727..3b25fff410b82d48ff05a1298f9a765f2197fa63 100644 (file)
@@ -159,6 +159,7 @@ done:
 
 static krb5_error_code ks_get_pac(krb5_context context,
                                  krb5_db_entry *client,
+                                 krb5_db_entry *server,
                                  krb5_keyblock *client_key,
                                  krb5_pac *pac)
 {
@@ -173,6 +174,7 @@ static krb5_error_code ks_get_pac(krb5_context context,
        code = mit_samba_get_pac(mit_ctx,
                                 context,
                                 client,
+                                server,
                                 client_key,
                                 pac);
        if (code != 0) {
@@ -439,7 +441,7 @@ krb5_error_code kdb_samba_db_sign_auth_data(krb5_context context,
         */
        if (with_pac && generate_pac) {
                DBG_DEBUG("Generate PAC for AS-REQ [%s]\n", client_name);
-               code = ks_get_pac(context, client_entry, client_key, &pac);
+               code = ks_get_pac(context, client_entry, server, client_key, &pac);
                if (code != 0) {
                        goto done;
                }
@@ -490,6 +492,7 @@ krb5_error_code kdb_samba_db_sign_auth_data(krb5_context context,
 
                                code = ks_get_pac(context,
                                                  client_entry,
+                                                 server,
                                                  client_key,
                                                  &pac);
                                if (code != 0 && code != ENOENT) {
index c2a604045d99124ea11d7e691935540f11dd46b3..df2ba0a906f25165ec542bf693701398718ff566 100644 (file)
@@ -407,6 +407,7 @@ int mit_samba_get_nextkey(struct mit_samba_context *ctx,
 int mit_samba_get_pac(struct mit_samba_context *smb_ctx,
                      krb5_context context,
                      krb5_db_entry *client,
+                     krb5_db_entry *server,
                      krb5_keyblock *client_key,
                      krb5_pac *pac)
 {
@@ -417,9 +418,12 @@ int mit_samba_get_pac(struct mit_samba_context *smb_ctx,
        DATA_BLOB **cred_ndr_ptr = NULL;
        DATA_BLOB cred_blob = data_blob_null;
        DATA_BLOB *pcred_blob = NULL;
+       DATA_BLOB *pac_attrs_blob = NULL;
+       DATA_BLOB *requester_sid_blob = NULL;
        NTSTATUS nt_status;
        krb5_error_code code;
        struct samba_kdc_entry *skdc_entry;
+       bool is_krbtgt;
 
        skdc_entry = talloc_get_type_abort(client->e_data,
                                           struct samba_kdc_entry);
@@ -438,12 +442,16 @@ int mit_samba_get_pac(struct mit_samba_context *smb_ctx,
        }
 #endif
 
+       is_krbtgt = ks_is_tgs_principal(smb_ctx, server->princ);
+
        nt_status = samba_kdc_get_pac_blobs(tmp_ctx,
                                            skdc_entry,
                                            &logon_info_blob,
                                            cred_ndr_ptr,
                                            &upn_dns_info_blob,
-                                           NULL, NULL, NULL,
+                                           is_krbtgt ? &pac_attrs_blob : NULL,
+                                           NULL,
+                                           is_krbtgt ? &requester_sid_blob : NULL,
                                            NULL);
        if (!NT_STATUS_IS_OK(nt_status)) {
                talloc_free(tmp_ctx);
@@ -471,8 +479,8 @@ int mit_samba_get_pac(struct mit_samba_context *smb_ctx,
                                   logon_info_blob,
                                   pcred_blob,
                                   upn_dns_info_blob,
-                                  NULL,
-                                  NULL,
+                                  pac_attrs_blob,
+                                  requester_sid_blob,
                                   NULL,
                                   pac);
 
@@ -496,6 +504,7 @@ krb5_error_code mit_samba_reget_pac(struct mit_samba_context *ctx,
        DATA_BLOB *pac_blob = NULL;
        DATA_BLOB *upn_blob = NULL;
        DATA_BLOB *deleg_blob = NULL;
+       DATA_BLOB *requester_sid_blob = NULL;
        struct samba_kdc_entry *client_skdc_entry = NULL;
        struct samba_kdc_entry *krbtgt_skdc_entry = NULL;
        struct samba_kdc_entry *server_skdc_entry = NULL;
@@ -511,8 +520,12 @@ krb5_error_code mit_samba_reget_pac(struct mit_samba_context *ctx,
        ssize_t upn_dns_info_idx = -1;
        ssize_t srv_checksum_idx = -1;
        ssize_t kdc_checksum_idx = -1;
+       ssize_t tkt_checksum_idx = -1;
+       ssize_t attrs_info_idx = -1;
+       ssize_t requester_sid_idx = -1;
        krb5_pac new_pac = NULL;
        bool ok;
+       bool is_krbtgt;
 
        /* Create a memory context early so code can use talloc_stackframe() */
        tmp_ctx = talloc_named(ctx, 0, "mit_samba_reget_pac context");
@@ -520,6 +533,8 @@ krb5_error_code mit_samba_reget_pac(struct mit_samba_context *ctx,
                return ENOMEM;
        }
 
+       is_krbtgt = ks_is_tgs_principal(ctx, server->princ);
+
        if (client != NULL) {
                client_skdc_entry =
                        talloc_get_type_abort(client->e_data,
@@ -578,7 +593,7 @@ krb5_error_code mit_samba_reget_pac(struct mit_samba_context *ctx,
                                                    NULL,
                                                    &upn_blob,
                                                    NULL, NULL,
-                                                   NULL,
+                                                   &requester_sid_blob,
                                                    NULL);
                if (!NT_STATUS_IS_OK(nt_status)) {
                        code = EINVAL;
@@ -737,6 +752,45 @@ krb5_error_code mit_samba_reget_pac(struct mit_samba_context *ctx,
                        }
                        kdc_checksum_idx = i;
                        break;
+               case PAC_TYPE_TICKET_CHECKSUM:
+                       if (tkt_checksum_idx != -1) {
+                               DBG_WARNING("ticket checksum type[%u] twice "
+                                           "[%zd] and [%zu]: \n",
+                                           types[i],
+                                           tkt_checksum_idx,
+                                           i);
+                               SAFE_FREE(types);
+                               code = EINVAL;
+                               goto done;
+                       }
+                       tkt_checksum_idx = i;
+                       break;
+               case PAC_TYPE_ATTRIBUTES_INFO:
+                       if (attrs_info_idx != -1) {
+                               DBG_WARNING("attributes info type[%u] twice "
+                                           "[%zd] and [%zu]: \n",
+                                           types[i],
+                                           attrs_info_idx,
+                                           i);
+                               SAFE_FREE(types);
+                               code = EINVAL;
+                               goto done;
+                       }
+                       attrs_info_idx = i;
+                       break;
+               case PAC_TYPE_REQUESTER_SID:
+                       if (requester_sid_idx != -1) {
+                               DBG_WARNING("requester sid type[%u] twice"
+                                           "[%zd] and [%zu]: \n",
+                                           types[i],
+                                           requester_sid_idx,
+                                           i);
+                               SAFE_FREE(types);
+                               code = EINVAL;
+                               goto done;
+                       }
+                       requester_sid_idx = i;
+                       break;
                default:
                        continue;
                }
@@ -766,6 +820,13 @@ krb5_error_code mit_samba_reget_pac(struct mit_samba_context *ctx,
                code = EINVAL;
                goto done;
        }
+       if (!(flags & KRB5_KDB_FLAG_CONSTRAINED_DELEGATION) &&
+           requester_sid_idx == -1) {
+               DEBUG(1, ("PAC_TYPE_REQUESTER_SID missing\n"));
+               SAFE_FREE(types);
+               code = KRB5KDC_ERR_TGT_REVOKED;
+               goto done;
+       }
 
        /* Build an updated PAC */
        code = krb5_pac_init(context, &new_pac);
@@ -831,6 +892,10 @@ krb5_error_code mit_samba_reget_pac(struct mit_samba_context *ctx,
                        }
                        break;
                case PAC_TYPE_SRV_CHECKSUM:
+                       if (requester_sid_idx == -1 && requester_sid_blob != NULL) {
+                               /* inject REQUESTER_SID */
+                               forced_next_type = PAC_TYPE_REQUESTER_SID;
+                       }
                        /*
                         * This is generated in the main KDC code
                         */
@@ -840,6 +905,26 @@ krb5_error_code mit_samba_reget_pac(struct mit_samba_context *ctx,
                         * This is generated in the main KDC code
                         */
                        continue;
+               case PAC_TYPE_ATTRIBUTES_INFO:
+                       if (!is_untrusted && is_krbtgt) {
+                               /* just copy... */
+                               break;
+                       }
+
+                       continue;
+               case PAC_TYPE_REQUESTER_SID:
+                       if (!is_krbtgt) {
+                               continue;
+                       }
+
+                       /*
+                        * Replace in the RODC case, otherwise
+                        * requester_sid_blob is NULL and we just copy.
+                        */
+                       if (requester_sid_blob != NULL) {
+                               type_blob = *requester_sid_blob;
+                       }
+                       break;
                default:
                        /* just copy... */
                        break;
index 636c77ec97cbe35cbb1536c0a8196de0c7ea1872..4431e82a1b2ec449f85582c0661635ed709eaebc 100644 (file)
@@ -50,6 +50,7 @@ int mit_samba_get_nextkey(struct mit_samba_context *ctx,
 int mit_samba_get_pac(struct mit_samba_context *smb_ctx,
                      krb5_context context,
                      krb5_db_entry *client,
+                     krb5_db_entry *server,
                      krb5_keyblock *client_key,
                      krb5_pac *pac);