public inbox for git-commits@fedoraproject.org
help / color / mirror / Atom feed
* [rpms/krb5] f44: GSSAPI: allow using cached S4U2Self ticket to itself
@ 2026-09-01 14:47 Julien Rische
  0 siblings, 0 replies; only message in thread
From: Julien Rische @ 2026-09-01 14:47 UTC (permalink / raw)
  To: git-commits

            A new commit has been pushed.

            Repo   : rpms/krb5
            Branch : f44
            Commit : 7e8fd475e6094352add9e441ff7d7a2bafbc9846
            Author : Julien Rische <jrische@redhat.com>
            Date   : 2026-09-01T10:49:35+02:00
            Stats  : +772/-50 in 1 file(s)
            URL    : https://src.fedoraproject.org/rpms/krb5/c/7e8fd475e6094352add9e441ff7d7a2bafbc9846?branch=f44

            Log:
            GSSAPI: allow using cached S4U2Self ticket to itself

- Add auto_fast_armor realm variable for FAST

---
diff --git a/krb5-1.22-redhat.patch b/krb5-1.22-redhat.patch
index 6ff97b8..a74e93a 100644
--- a/krb5-1.22-redhat.patch
+++ b/krb5-1.22-redhat.patch
@@ -1,7 +1,7 @@
 From d7d716f3270235529995e0d28b8d6c89f4171045 Mon Sep 17 00:00:00 2001
 From: Robbie Harwood <rharwood@redhat.com>
 Date: Fri, 9 Nov 2018 15:12:21 -0500
-Subject: [PATCH 01/25] FIPS: Add support for PRNG, RADIUS (krad), and crypto
+Subject: [PATCH 01/28] FIPS: Add support for PRNG, RADIUS (krad), and crypto
  providers
 
 In FIPS mode:
@@ -656,13 +656,13 @@ index 1a772d450f..32baaecbb8 100644
      vt->name = "spake";
      vt->pa_type_list = pa_types;
 -- 
-2.53.0
+2.55.0
 
 
 From 1a4d6a7393887bf5372674942eea53030de0fed9 Mon Sep 17 00:00:00 2001
 From: Julien Rische <jrische@redhat.com>
 Date: Thu, 5 May 2022 17:15:12 +0200
-Subject: [PATCH 02/25] FIPS: Allow krad UDP/TCP localhost connection
+Subject: [PATCH 02/28] FIPS: Allow krad UDP/TCP localhost connection
 
 libkrad allows to establish connections only to UNIX socket in FIPS
 mode, because MD5 digest is not considered safe enough to be used for
@@ -740,13 +740,13 @@ index 891404d5b7..7654bab21b 100644
          retval = ESOCKTNOSUPPORT;
          goto error;
 -- 
-2.53.0
+2.55.0
 
 
 From 9b5aa1ecb9b49d684534bffbad39f08358f797e3 Mon Sep 17 00:00:00 2001
 From: Julien Rische <jrische@redhat.com>
 Date: Tue, 23 May 2023 12:19:54 +0200
-Subject: [PATCH 03/25] FIPS: Make PKINIT CMS SHA-1 signature verification
+Subject: [PATCH 03/28] FIPS: Make PKINIT CMS SHA-1 signature verification
  available
 
 We recommend using the SHA1 crypto-module in order to allow the
@@ -786,13 +786,13 @@ index f222dbdf92..1d99559485 100644
          goto cleanup;
      }
 -- 
-2.53.0
+2.55.0
 
 
 From c082c835672d41b9a68d1d3195fe0c44cb689fd7 Mon Sep 17 00:00:00 2001
 From: Julien Rische <jrische@redhat.com>
 Date: Thu, 19 Jan 2023 19:22:27 +0100
-Subject: [PATCH 04/25] FIPS: Allow KRB5KDF, MD5, MD4 and HMAC-MD4/5
+Subject: [PATCH 04/28] FIPS: Allow KRB5KDF, MD5, MD4 and HMAC-MD4/5
 
 OpenSSL's restrictions to use KRB5KDF, MD5, and MD4 in FIPS mode are
 bypassed in case AES SHA-1 HMAC or RC4 encryption types are allowed by
@@ -1218,13 +1218,13 @@ index 7654bab21b..96da3c451d 100644
  static bool is_inet_localhost(struct addrinfo *info)
  {
 -- 
-2.53.0
+2.55.0
 
 
 From c64ff3431496d96f30ac1303be3a5aedf518cab1 Mon Sep 17 00:00:00 2001
 From: Robbie Harwood <rharwood@redhat.com>
 Date: Tue, 26 Mar 2019 18:51:10 -0400
-Subject: [PATCH 05/25] 3DES: Remove support
+Subject: [PATCH 05/28] 3DES: Remove support
 
 Completely remove support for all DES3 enctypes (des3-cbc-raw,
 des3-hmac-sha1, des3-cbc-sha1-kd).  Update all tests and documentation
@@ -7498,13 +7498,13 @@ index 1aebdd0b4a..c38eefd2bd 100644
       <td>The AES Advanced Encryption Standard
  family, like 3DES, is a symmetric block cipher and was designed
 -- 
-2.53.0
+2.55.0
 
 
 From f6b425e86cec7feb91d62a9d312f2660f06ac2ac Mon Sep 17 00:00:00 2001
 From: Robbie Harwood <rharwood@redhat.com>
 Date: Tue, 23 Aug 2016 16:29:58 -0400
-Subject: [PATCH 06/25] PAM: Add integration to ksu
+Subject: [PATCH 06/28] PAM: Add integration to ksu
 
 Modify ksu so that it performs account and session management on behalf of
 the target user account, mimicking the action of regular su.  The default
@@ -8278,13 +8278,13 @@ index 9fc569f195..99268dfd78 100644
  if test "${localedir+set}" != set; then
      localedir='$(datadir)/locale'
 -- 
-2.53.0
+2.55.0
 
 
 From dac2e975d5729d53f22dc7d77428feb55263b982 Mon Sep 17 00:00:00 2001
 From: Robbie Harwood <rharwood@redhat.com>
 Date: Tue, 23 Aug 2016 16:30:53 -0400
-Subject: [PATCH 07/25] SELINUX: Add integration
+Subject: [PATCH 07/28] SELINUX: Add integration
 
 SELinux bases access to files on the domain of the requesting process,
 the operation being performed, and the context applied to the file.
@@ -9320,13 +9320,13 @@ index 0000000000..b10f927b2e
 +
 +#endif /* USE_SELINUX */
 -- 
-2.53.0
+2.55.0
 
 
 From 8523c362c7a0bc2a702ede1ec82b24555ff12ba5 Mon Sep 17 00:00:00 2001
 From: Julien Rische <jrische@redhat.com>
 Date: Mon, 9 Jan 2023 22:39:52 +0100
-Subject: [PATCH 08/25] INSTALL: Do not set root as ksu file owner
+Subject: [PATCH 08/28] INSTALL: Do not set root as ksu file owner
 
 Upstream Makefile uses the install command to set root as owner of the
 ksu executable file. However, this is no longer supported on latest
@@ -9352,13 +9352,13 @@ index 9f64fd190f..3724d26ae6 100644
  ## ${prefix}.
  prefix=@prefix@
 -- 
-2.53.0
+2.55.0
 
 
 From 307d0b16159de59092b00a109d44f68de323f5f1 Mon Sep 17 00:00:00 2001
 From: Julien Rische <jrische@redhat.com>
 Date: Wed, 7 Dec 2022 13:22:42 +0100
-Subject: [PATCH 09/25] SSSD: Make tests compatible with
+Subject: [PATCH 09/28] SSSD: Make tests compatible with
  sssd_krb5_locator_plugin.so
 
 The sssd_krb5_locator_plugin.so plugin provided by sssd-client conflicts
@@ -9394,13 +9394,13 @@ index 87bac17929..26bc95a8dc 100644
          fail('URI answers do not match')
      j += 1
 -- 
-2.53.0
+2.55.0
 
 
 From 82ec4d257ba4f0ea5e57c56b680bc888b69ae3df Mon Sep 17 00:00:00 2001
 From: Julien Rische <jrische@redhat.com>
 Date: Wed, 15 Mar 2023 15:56:34 +0100
-Subject: [PATCH 10/25] PAC: Allow to set ticket signature as optional
+Subject: [PATCH 10/28] PAC: Allow to set ticket signature as optional
 
 MS-PAC states that "The ticket signature SHOULD be included in tickets
 that are not encrypted to the krbtgt account". However, the
@@ -9674,13 +9674,13 @@ index 15ddc17dc5..96cdd52982 100644
  .sp
  This command requires the \fBmodify\fP privilege.
 -- 
-2.53.0
+2.55.0
 
 
 From f160430a84cdbc2f24e4e9dc32fafac04ddcb887 Mon Sep 17 00:00:00 2001
 From: Robbie Harwood <rharwood@redhat.com>
 Date: Tue, 23 Aug 2016 16:49:25 -0400
-Subject: [PATCH 11/25] BUILD: fix debuginfo with y.tab.c
+Subject: [PATCH 11/28] BUILD: fix debuginfo with y.tab.c
 
 We want to keep these y.tab.c files around because the debuginfo points to
 them.  It would be more elegant at the end to use symbolic links, but that
@@ -9731,13 +9731,13 @@ index 8669c2436c..f243017ce9 100644
 -	$(RM) $(PROG) $(OBJS) getdate.c
 +	$(RM) $(PROG) $(OBJS) getdate.c y.tab.c
 -- 
-2.53.0
+2.55.0
 
 
 From 621dac3f7d2989adfd746d40ba74468fa0275ab5 Mon Sep 17 00:00:00 2001
 From: Alexander Bokovoy <abokovoy@redhat.com>
 Date: Sun, 21 Sep 2025 11:14:51 +0300
-Subject: [PATCH 12/25] PKINIT: If configured, attempt Anonymous PKINIT for
+Subject: [PATCH 12/28] PKINIT: If configured, attempt Anonymous PKINIT for
  FAST
 
 If auto_fast_armor is configured for the realm or globally, optimistically
@@ -9959,13 +9959,13 @@ index 6f7890abcd..12c2ea1e5d 100644
  Specifies the name of the host\(aqs site for the purpose of DNS\-based
  KDC discovery for this realm.  New in release 1.22.
 -- 
-2.53.0
+2.55.0
 
 
 From 347f81103e95536b5655bee31bb9ced05d06b098 Mon Sep 17 00:00:00 2001
 From: Alexander Bokovoy <abokovoy@redhat.com>
 Date: Sun, 19 Oct 2025 18:14:29 +0300
-Subject: [PATCH 13/25] Fix OTP preauth crash with null prompter
+Subject: [PATCH 13/28] Fix OTP preauth crash with null prompter
 
 In doprompt(), check if the caller provided a prompter before
 dereferencing it.  Similar code returns either EIO or
@@ -9995,13 +9995,13 @@ index 07ffc15c22..48003da62f 100644
          return EINVAL;
  
 -- 
-2.53.0
+2.55.0
 
 
 From 2073be1acd51f906ac68c1a73c4f1ae8380eee35 Mon Sep 17 00:00:00 2001
 From: Alexander Bokovoy <abokovoy@redhat.com>
 Date: Wed, 10 Dec 2025 10:42:02 +0200
-Subject: [PATCH 14/25] Fix strchr() conformance to C23
+Subject: [PATCH 14/28] Fix strchr() conformance to C23
 
 C23 7.28.5.1 specifies search functions such as strchr() as generic,
 returning const char * if the first argument is of type const char *.
@@ -10185,13 +10185,13 @@ index 82f870ea5d..4221a20283 100644
                  key = strdup(data->otp_answer);
                  if (key == NULL)
 -- 
-2.53.0
+2.55.0
 
 
 From df905ea146a4feb39275f657918373e343cda28f Mon Sep 17 00:00:00 2001
 From: Greg Hudson <ghudson@mit.edu>
 Date: Sun, 28 Sep 2025 15:39:10 -0400
-Subject: [PATCH 15/25] Add paChecksum2 to PKINIT ASN.1 tests
+Subject: [PATCH 15/28] Add paChecksum2 to PKINIT ASN.1 tests
 
 Commit 310793ba63782af5ffa3a95d20e41f8f03ca7e00 added the paChecksum2
 field to krb5_pk_authenticator.  ktest_make_sample_pk_authenticator()
@@ -10360,13 +10360,13 @@ index c47bd71f67..418be63546 100644
  .  [2] [Sequence/Sequence Of]
  .  .  [Sequence/Sequence Of]
 -- 
-2.53.0
+2.55.0
 
 
 From c851405051ca0af7779a6d6f40df4f28221230f3 Mon Sep 17 00:00:00 2001
 From: Dax Kelson <dakelson@redhat.com>
 Date: Tue, 13 May 2025 11:54:41 -0600
-Subject: [PATCH 16/25] Add xrealmauthz KDC policy module and tests
+Subject: [PATCH 16/28] Add xrealmauthz KDC policy module and tests
 
 This module provides fine-grained access control for cross-realm
 authentications by checking string attributes on the incoming
@@ -11121,13 +11121,13 @@ index 0000000000..3b3921f036
 +
 +success('Cross-realm authorization tests completed successfully')
 -- 
-2.53.0
+2.55.0
 
 
 From 4634ca1f8242c24632e006d7b651064a7556cc92 Mon Sep 17 00:00:00 2001
 From: Julien Rische <jrische@redhat.com>
 Date: Thu, 29 Jan 2026 19:05:01 +0100
-Subject: [PATCH 17/25] Install xrealmauthz like other plugins
+Subject: [PATCH 17/28] Install xrealmauthz like other plugins
 
 The xrealmauthz kdcpolicy plugin was merged upstream, but it is not
 installed my the Makefile. The commit adds additional configuration to
@@ -11185,13 +11185,13 @@ index 78346d6572..b6740210a7 100644
  @libnover_frag@
  @libobj_frag@
 -- 
-2.53.0
+2.55.0
 
 
 From 6d066787d23c913789dcfc220b34cd3a78ada4c7 Mon Sep 17 00:00:00 2001
 From: Julien Rische <jrische@redhat.com>
 Date: Mon, 16 Feb 2026 16:30:14 +0100
-Subject: [PATCH 18/25] Force "fork" method for RADIUS daemon in OTP test
+Subject: [PATCH 18/28] Force "fork" method for RADIUS daemon in OTP test
 
 The RADIUS daemon used in the OTP test relies on
 multiprocessing.Process. Since Python 3.14, multiprocessing changed its
@@ -11255,13 +11255,13 @@ index dd5cdc5c26..c173b55c41 100755
  daemon2 = UnixRadiusDaemon(args=(socket_file, None, 'accept2', queue2))
  daemon1.start()
 -- 
-2.53.0
+2.55.0
 
 
 From 4d8e778bdbf6476e8aa397ef046126ae532f03d6 Mon Sep 17 00:00:00 2001
 From: Alexander Bokovoy <abokovoy@redhat.com>
 Date: Sun, 8 Mar 2026 21:50:52 +0200
-Subject: [PATCH 19/25] Fix S4U2Self ignoring time_req when acquiring
+Subject: [PATCH 19/28] Fix S4U2Self ignoring time_req when acquiring
  impersonated credentials
 MIME-Version: 1.0
 Content-Type: text/plain; charset=UTF-8
@@ -11326,13 +11326,13 @@ index fa7f980af7..9f2cbebec7 100644
          subject_cert = user->princ->data;
      else
 -- 
-2.53.0
+2.55.0
 
 
 From 5b185893438f775538a8d6340e9f4f39f6383cc7 Mon Sep 17 00:00:00 2001
 From: Alexander Bokovoy <abokovoy@redhat.com>
 Date: Mon, 9 Mar 2026 09:16:56 +0200
-Subject: [PATCH 20/25] Fix S4U2Self ignoring time_req when copying
+Subject: [PATCH 20/28] Fix S4U2Self ignoring time_req when copying
  impersonator TGT
 
 gss_acquire_cred_impersonate_name() with a time_req bounded the
@@ -11406,13 +11406,13 @@ index 9f2cbebec7..10288ebe94 100644
          goto cleanup;
  
 -- 
-2.53.0
+2.55.0
 
 
 From 8df1c41911e7179d2e6cdb72b3bb568c1db08bd3 Mon Sep 17 00:00:00 2001
 From: Alexander Bokovoy <abokovoy@redhat.com>
 Date: Mon, 9 Mar 2026 09:17:08 +0200
-Subject: [PATCH 21/25] Add t_s4u test for time_req bounding all delegated-cred
+Subject: [PATCH 21/28] Add t_s4u test for time_req bounding all delegated-cred
  tickets
 
 Add --time-req N option to t_s4u and a check_cred_endtimes() function
@@ -11568,13 +11568,13 @@ index 4a1cdb2355..813e27fc15 100755
  # try krb5 -> S4U2Proxy.
  realm.kinit(realm.user_princ, None, ['-f', '-k', '-c', usercache,
 -- 
-2.53.0
+2.55.0
 
 
 From e79cc39961a0e347e2efc0455d62ea64fdff99ea Mon Sep 17 00:00:00 2001
 From: Samuel Cabrero <scabrero@suse.com>
 Date: Tue, 17 Feb 2026 16:57:40 +0100
-Subject: [PATCH 22/25] Make configure.ac work with autoconf 2.73
+Subject: [PATCH 22/28] Make configure.ac work with autoconf 2.73
 
 autoreconf requires "AC_INIT" to appear in configure.ac.  Prior to
 autoconf 2.73, our indirect invocation via K5_AC_INIT() was
@@ -11662,13 +11662,13 @@ index 0000000000..4b08edde52
 +m4_define([K5_VERSION],PL_KRB5_MAJOR_RELEASE.PL_KRB5_MINOR_RELEASE[]ifelse(PL_KRB5_PATCHLEVEL,0,,.PL_KRB5_PATCHLEVEL)ifelse(PL_KRB5_RELTAIL,,,-PL_KRB5_RELTAIL))
 +m4_define([K5_BUGADDR],krb5-bugs@mit.edu)
 -- 
-2.53.0
+2.55.0
 
 
 From a79620c4f0080f436ecae3504c2e0ee3fedb5360 Mon Sep 17 00:00:00 2001
 From: Greg Hudson <ghudson@mit.edu>
 Date: Wed, 25 Feb 2026 19:05:40 -0500
-Subject: [PATCH 23/25] Use X509_check_host() to verify KKDCP server cert
+Subject: [PATCH 23/28] Use X509_check_host() to verify KKDCP server cert
 
 In the k5tls module, rely on X509_check_host() and
 X509_check_ip_asc(), which were added in OpenSSL 1.0.2, instead of
@@ -11915,13 +11915,13 @@ index aab67c01cb..42d72dc9ec 100644
  
  static int
 -- 
-2.53.0
+2.55.0
 
 
 From c75afd347838de097522095016690e851f055fa1 Mon Sep 17 00:00:00 2001
 From: Bob Beck <beck@openssl.org>
 Date: Mon, 16 Feb 2026 15:15:55 -0700
-Subject: [PATCH 24/25] Improve future OpenSSL compatibility
+Subject: [PATCH 24/28] Improve future OpenSSL compatibility
 
 Avoid calling deprecated OpenSSL functions when compiling against
 versions of OpenSSL where they are deprecated.  Add
@@ -12200,13 +12200,13 @@ index 42d72dc9ec..7763327b7a 100644
          goto error;
  
 -- 
-2.53.0
+2.55.0
 
 
 From 3cf396189876ac661063dc2483ea721d8a8c7441 Mon Sep 17 00:00:00 2001
 From: Greg Hudson <ghudson@mit.edu>
 Date: Wed, 8 Apr 2026 17:57:59 -0400
-Subject: [PATCH 25/25] Fix two NegoEx parsing vulnerabilities
+Subject: [PATCH 25/28] Fix two NegoEx parsing vulnerabilities
 
 In parse_nego_message(), check the result of the second call to
 vector_base() before dereferencing it.  In parse_message(), check for
@@ -12266,5 +12266,727 @@ index edc5462e84..a65238e573 100644
          return GSS_S_DEFECTIVE_TOKEN;
      }
 -- 
-2.53.0
+2.55.0
+
+
+From 5fea7c52d5fad2c41418c3d3f46b890f01051377 Mon Sep 17 00:00:00 2001
+From: Julien Rische <jrische@redhat.com>
+Date: Tue, 1 Sep 2026 10:35:55 +0200
+Subject: [PATCH 26/28] Revert "PKINIT: If configured, attempt Anonymous PKINIT
+ for FAST"
+
+This reverts commit 621dac3f7d2989adfd746d40ba74468fa0275ab5.
+---
+ src/lib/krb5/krb/fast.c | 118 ----------------------------------------
+ src/lib/krb5/krb/fast.h |   2 -
+ src/man/krb5.conf.man   |  13 -----
+ 3 files changed, 133 deletions(-)
+
+diff --git a/src/lib/krb5/krb/fast.c b/src/lib/krb5/krb/fast.c
+index ee2e081892..62c9f0841f 100644
+--- a/src/lib/krb5/krb/fast.c
++++ b/src/lib/krb5/krb/fast.c
+@@ -168,109 +168,6 @@ krb5int_fast_prep_req_body(krb5_context context,
+     return retval;
+ }
+ 
+-static krb5_boolean
+-fast_is_pkinit_allowed(krb5_context context, krb5_data *realm)
+-{
+-    int value;
+-    krb5_error_code retval = EINVAL;
+-    char realmstr[1024];
+-    const char *option = "auto_fast_armor";
+-    const int def_value = FALSE;
+-
+-    if (realm != NULL && realm->length > sizeof(realmstr)-1)
+-        return FALSE;
+-
+-    if (realm != NULL) {
+-        strncpy(realmstr, realm->data, realm->length);
+-        realmstr[realm->length] = '\0';
+-
+-        retval = profile_get_boolean(context->profile,
+-                                     KRB5_CONF_REALMS, realmstr,
+-                                     option, def_value, &value);
+-    }
+-
+-    return retval ? FALSE : value;
+-
+-}
+-
+-static krb5_error_code
+-fast_acquire_pkinit_armor(krb5_context context,
+-                           struct krb5int_fast_request_state *state,
+-                           krb5_get_init_creds_opt *opt, krb5_kdc_req *request)
+-{
+-    krb5_context ctx;
+-    krb5_get_init_creds_opt *options = NULL;
+-    krb5_error_code retval = 0;
+-    krb5_data *target_realm = &request->server->realm;
+-    krb5_creds creds;
+-    krb5_principal anon_princ = NULL;
+-    krb5_ccache out_cc;
+-
+-    /* short circuit, we are asked to perform Anonymous PKINIT already */
+-    if (opt->flags & KRB5_GET_INIT_CREDS_OPT_ANONYMOUS) {
+-        return EINVAL;
+-    }
+-
+-    /* skip realms which do not allow use of automated FAST armor */
+-    if (!fast_is_pkinit_allowed(context, target_realm)) {
+-        return EINVAL;
+-    }
+-
+-    retval = krb5_init_context(&ctx);
+-    if (retval != 0) {
+-        return retval;
+-    }
+-    retval = krb5_get_init_creds_opt_alloc(ctx, &options);
+-    if (retval != 0) {
+-        goto cleanup;
+-    }
+-    krb5_get_init_creds_opt_set_anonymous(options, 1);
+-    retval = krb5_cc_new_unique(ctx, "MEMORY", NULL, &out_cc);
+-    if (retval != 0) {
+-        goto cleanup;
+-    }
+-
+-    retval = krb5_get_init_creds_opt_set_out_ccache(ctx, options, out_cc);
+-    if (retval != 0) {
+-        goto cleanup;
+-    }
+-
+-    retval = krb5_build_principal_ext(ctx, &anon_princ,
+-                                      target_realm->length, target_realm->data,
+-                                      strlen(KRB5_WELLKNOWN_NAMESTR),
+-                                      KRB5_WELLKNOWN_NAMESTR,
+-                                      strlen(KRB5_ANONYMOUS_PRINCSTR),
+-                                      KRB5_ANONYMOUS_PRINCSTR, 0);
+-    if (retval != 0) {
+-        goto cleanup;
+-    }
+-
+-    retval = krb5_get_init_creds_password(ctx, &creds, anon_princ, 0,
+-                                          NULL /* no prompter */, NULL,
+-                                          0, NULL /* service name */,
+-                                          options);
+-    if (retval == 0) {
+-        state->fast_state_flags |= KRB5INT_FAST_OWN_ARMOR;
+-        state->armor_ccache = out_cc;
+-    }
+-cleanup:
+-    if (retval != 0 && out_cc != NULL) {
+-        (void) krb5_cc_destroy(ctx, out_cc);
+-    }
+-    if (retval == 0) {
+-        krb5_free_cred_contents(ctx, &creds);
+-    }
+-    if (options != NULL) {
+-        krb5_get_init_creds_opt_free(ctx, options);
+-    }
+-    if (anon_princ != NULL) {
+-        krb5_free_principal(ctx, anon_princ);
+-    }
+-    krb5_free_context(ctx);
+-
+-    return retval;
+-}
+-
+ krb5_error_code
+ krb5int_fast_as_armor(krb5_context context,
+                       struct krb5int_fast_request_state *state,
+@@ -281,20 +178,10 @@ krb5int_fast_as_armor(krb5_context context,
+     krb5_principal target_principal = NULL;
+     krb5_data *target_realm;
+     const char *ccname = k5_gic_opt_get_fast_ccache_name(opt);
+-    char *fast_ccname = NULL;
+     krb5_flags fast_flags;
+ 
+     krb5_clear_error_message(context);
+     target_realm = &request->server->realm;
+-    if (ccname == NULL) {
+-        retval = fast_acquire_pkinit_armor(context, state, opt, request);
+-        if (retval == 0) {
+-            retval = krb5_cc_get_full_name(context, state->armor_ccache, &fast_ccname);
+-            if (retval == 0 && fast_ccname != NULL)
+-                ccname = fast_ccname;
+-        }
+-        retval = 0;
+-    }
+     if (ccname != NULL) {
+         TRACE_FAST_ARMOR_CCACHE(context, ccname);
+         state->fast_state_flags |= KRB5INT_FAST_ARMOR_AVAIL;
+@@ -333,8 +220,6 @@ krb5int_fast_as_armor(krb5_context context,
+         krb5_cc_close(context, ccache);
+     if (target_principal)
+         krb5_free_principal(context, target_principal);
+-    if (fast_ccname)
+-        free(fast_ccname);
+     return retval;
+ }
+ 
+@@ -730,9 +615,6 @@ krb5int_fast_free_state(krb5_context context,
+     /*We are responsible for none of the store in the fast_outer_req*/
+     krb5_free_keyblock(context, state->armor_key);
+     krb5_free_fast_armor(context, state->armor);
+-    if (state->fast_state_flags & KRB5INT_FAST_OWN_ARMOR) {
+-        krb5_cc_destroy(context, state->armor_ccache);
+-    }
+     free(state);
+ }
+ 
+diff --git a/src/lib/krb5/krb/fast.h b/src/lib/krb5/krb/fast.h
+index e5fe8bd544..7156ea203f 100644
+--- a/src/lib/krb5/krb/fast.h
++++ b/src/lib/krb5/krb/fast.h
+@@ -34,7 +34,6 @@ struct krb5int_fast_request_state {
+     krb5_kdc_req fast_outer_request;
+     krb5_keyblock *armor_key; /*non-null means fast is in use*/
+     krb5_fast_armor *armor;
+-    krb5_ccache armor_ccache;
+     krb5_ui_4 fast_state_flags;
+     krb5_ui_4 fast_options;
+     krb5_int32 nonce;
+@@ -42,7 +41,6 @@ struct krb5int_fast_request_state {
+ 
+ #define KRB5INT_FAST_DO_FAST     (1l<<0)  /* Perform FAST */
+ #define KRB5INT_FAST_ARMOR_AVAIL (1l<<1)
+-#define KRB5INT_FAST_OWN_ARMOR   (1l<<2)
+ 
+ krb5_error_code
+ krb5int_fast_prep_req_body(krb5_context context,
+diff --git a/src/man/krb5.conf.man b/src/man/krb5.conf.man
+index 12c2ea1e5d..6f7890abcd 100644
+--- a/src/man/krb5.conf.man
++++ b/src/man/krb5.conf.man
+@@ -655,19 +655,6 @@ primary KDC, in case the user\(aqs password has just been changed, and
+ the updated database has not been propagated to the replica
+ servers yet.  New in release 1.19.
+ .TP
+-\fBauto_fast_armor\fP
+-If this flag is true, then initial ticket request will use Anonymous
+-PKINIT to protect the communication as a FAST channel in case an application
+-did not provide its own FAST channel. This is useful for deployments where
+-pre-authentication methods require use of the FAST channel, such as
+-passwordless methods provided by FreeIPA. Microsoft Active Directory
+-implementation of PKINIT does not support Anonymous PKINIT feature.
+-As a result, \fIauto_fast_armor\fP defaults to false.
+-.sp
+-Use of \fIauto_fast_armor = true\fP requires properly configured PKINIT and
+-WELLKNOWN/ANONYMOUS principal defined on the KDC side. Consult KDC documentation
+-for details.
+-.TP
+ \fBsitename\fP
+ Specifies the name of the host\(aqs site for the purpose of DNS\-based
+ KDC discovery for this realm.  New in release 1.22.
+-- 
+2.55.0
+
+
+From e2a20d4b567f1bc693bdf2544fb06859f1d68342 Mon Sep 17 00:00:00 2001
+From: jason34105533 <a20040108jason@gmail.com>
+Date: Thu, 23 Jul 2026 16:44:15 +0800
+Subject: [PATCH 27/28] Add auto_fast_armor realm variable
+
+When auto_fast_armor is true and no FAST ccache name is provided in
+the GIC options, use anonymous PKINIT to acquire an armor ticket into
+a temporary memory ccache.  Refactor krb5int_fast_as_armor() and add
+an armor_ccache parameter so that we can pass in the memory ccache
+without modifying the caller's GIC options.
+
+[ghudson@mit.edu: edited commit messages, documentation, and comments;
+refactored some code changes for simplicity]
+
+ticket: 9226 (new)
+(cherry picked from commit eaff3bcf1a43541208b1fa63a3df50c2080458b7)
+---
+ doc/admin/conf_files/krb5_conf.rst |  11 +++
+ src/include/k5-int.h               |   1 +
+ src/include/k5-trace.h             |   6 +-
+ src/lib/krb5/krb/fast.c            |  79 ++++++++++----------
+ src/lib/krb5/krb/fast.h            |   3 +-
+ src/lib/krb5/krb/get_in_tkt.c      | 111 ++++++++++++++++++++++++++++-
+ src/lib/krb5/krb/init_creds_ctx.h  |   4 ++
+ src/tests/gssapi/t_gssapi.py       |  18 +++++
+ src/tests/t_pkinit.py              |  27 +++++--
+ 9 files changed, 215 insertions(+), 45 deletions(-)
+
+diff --git a/doc/admin/conf_files/krb5_conf.rst b/doc/admin/conf_files/krb5_conf.rst
+index 160a8f1fd4..4a6b5d6857 100644
+--- a/doc/admin/conf_files/krb5_conf.rst
++++ b/doc/admin/conf_files/krb5_conf.rst
+@@ -487,6 +487,17 @@ following tags may be specified in the realm's subsection:
+     names to local user names.  The tag is the mapping name, and the
+     value is the corresponding local user name.
+ 
++**auto_fast_armor**
++    If this flag is true, initial credential acquisition will acquire
++    an anonymous PKINIT ticket to use as FAST armor before making the
++    real ticket request, unless an armor ccache is already configured
++    (as with kinit's **-T** option).  This flag allows
++    preauthentication mechanisms that require FAST, such as OTP, to
++    work without a pre-existing ticket.  This flag should only be set
++    for realms known to support anonymous PKINIT.  This flag has no
++    effect if the client principal is itself the anonymous principal.
++    The default value is false.  New in release 1.23.
++
+ **default_domain**
+     This tag specifies the domain used to expand hostnames when
+     translating Kerberos 4 service principals to Kerberos 5 principals
+diff --git a/src/include/k5-int.h b/src/include/k5-int.h
+index 252c8d9b00..58e785111d 100644
+--- a/src/include/k5-int.h
++++ b/src/include/k5-int.h
+@@ -185,6 +185,7 @@ typedef unsigned char   u_char;
+ #define KRB5_CONF_ALLOW_WEAK_CRYPTO            "allow_weak_crypto"
+ #define KRB5_CONF_AUTH_TO_LOCAL                "auth_to_local"
+ #define KRB5_CONF_AUTH_TO_LOCAL_NAMES          "auth_to_local_names"
++#define KRB5_CONF_AUTO_FAST_ARMOR              "auto_fast_armor"
+ #define KRB5_CONF_CANONICALIZE                 "canonicalize"
+ #define KRB5_CONF_CCACHE_TYPE                  "ccache_type"
+ #define KRB5_CONF_CLOCKSKEW                    "clockskew"
+diff --git a/src/include/k5-trace.h b/src/include/k5-trace.h
+index 5d0be63bf0..5aefd098a6 100644
+--- a/src/include/k5-trace.h
++++ b/src/include/k5-trace.h
+@@ -173,8 +173,8 @@ void krb5int_trace(krb5_context context, const char *fmt, ...);
+ #define TRACE_DNS_URI_SEND(c, domain)                   \
+     TRACE(c, "Sending DNS URI query for {str}", domain)
+ 
+-#define TRACE_FAST_ARMOR_CCACHE(c, ccache_name)         \
+-    TRACE(c, "FAST armor ccache: {str}", ccache_name)
++#define TRACE_FAST_ARMOR_CCACHE(c, ccache)              \
++    TRACE(c, "FAST armor ccache: {ccache}", ccache)
+ #define TRACE_FAST_ARMOR_CCACHE_KEY(c, keyblock)                \
+     TRACE(c, "Armor ccache session key: {keyblock}", keyblock)
+ #define TRACE_FAST_ARMOR_KEY(c, keyblock)               \
+@@ -217,6 +217,8 @@ void krb5int_trace(krb5_context context, const char *fmt, ...);
+ 
+ #define TRACE_INIT_CREDS(c, princ)                              \
+     TRACE(c, "Getting initial credentials for {princ}", princ)
++#define TRACE_INIT_CREDS_AUTO_FAST_ARMOR(c)                             \
++    TRACE(c, "Acquiring anonymous PKINIT armor ticket for FAST")
+ #define TRACE_INIT_CREDS_AS_KEY_GAK(c, keyblock)                        \
+     TRACE(c, "AS key obtained from gak_fct: {keyblock}", keyblock)
+ #define TRACE_INIT_CREDS_AS_KEY_PREAUTH(c, keyblock)                    \
+diff --git a/src/lib/krb5/krb/fast.c b/src/lib/krb5/krb/fast.c
+index 62c9f0841f..f9bef7f6b0 100644
+--- a/src/lib/krb5/krb/fast.c
++++ b/src/lib/krb5/krb/fast.c
+@@ -171,55 +171,62 @@ krb5int_fast_prep_req_body(krb5_context context,
+ krb5_error_code
+ krb5int_fast_as_armor(krb5_context context,
+                       struct krb5int_fast_request_state *state,
+-                      krb5_get_init_creds_opt *opt, krb5_kdc_req *request)
++                      krb5_get_init_creds_opt *opt,
++                      krb5_ccache armor_ccache, krb5_kdc_req *request)
+ {
+     krb5_error_code retval = 0;
+     krb5_ccache ccache = NULL;
+     krb5_principal target_principal = NULL;
+-    krb5_data *target_realm;
++    krb5_data *target_realm, config_data = empty_data();
+     const char *ccname = k5_gic_opt_get_fast_ccache_name(opt);
+     krb5_flags fast_flags;
+ 
+     krb5_clear_error_message(context);
+     target_realm = &request->server->realm;
+-    if (ccname != NULL) {
+-        TRACE_FAST_ARMOR_CCACHE(context, ccname);
+-        state->fast_state_flags |= KRB5INT_FAST_ARMOR_AVAIL;
++
++    if (armor_ccache == NULL) {
++        /* Stop if no armor ccache was provided by the direct caller or the GIC
++         * options. */
++        if (ccname == NULL)
++            return 0;
++        /* Resolve the armor ccache name provided in the GIC options. */
+         retval = krb5_cc_resolve(context, ccname, &ccache);
+-        if (retval == 0) {
+-            retval = krb5int_tgtname(context, target_realm, target_realm,
+-                                     &target_principal);
+-        }
+-        if (retval == 0) {
+-            krb5_data config_data;
+-            config_data.data = NULL;
+-            retval = krb5_cc_get_config(context, ccache, target_principal,
+-                                        KRB5_CC_CONF_FAST_AVAIL, &config_data);
+-            if ((retval == 0) && config_data.data) {
+-                TRACE_FAST_CCACHE_CONFIG(context);
+-                state->fast_state_flags |= KRB5INT_FAST_DO_FAST;
+-            }
+-            krb5_free_data_contents(context, &config_data);
+-            retval = 0;
+-        }
+-        fast_flags = k5_gic_opt_get_fast_flags(opt);
+-        if (fast_flags & KRB5_FAST_REQUIRED) {
+-            TRACE_FAST_REQUIRED(context);
+-            state->fast_state_flags |= KRB5INT_FAST_DO_FAST;
+-        }
+-        if (retval == 0 && (state->fast_state_flags & KRB5INT_FAST_DO_FAST)) {
+-            retval = fast_armor_ap_request(context, state, ccache,
+-                                           target_principal);
+-        }
+-        if (retval != 0) {
+-            k5_prependmsg(context, retval,
+-                          _("Error constructing AP-REQ armor"));
+-        }
++        if (retval)
++            goto cleanup;
++        armor_ccache = ccache;
++    }
++
++    TRACE_FAST_ARMOR_CCACHE(context, armor_ccache);
++
++    state->fast_state_flags |= KRB5INT_FAST_ARMOR_AVAIL;
++    retval = krb5int_tgtname(context, target_realm, target_realm,
++                             &target_principal);
++    if (retval)
++        goto cleanup;
++
++    retval = krb5_cc_get_config(context, armor_ccache, target_principal,
++                                KRB5_CC_CONF_FAST_AVAIL, &config_data);
++    if (!retval && config_data.data != NULL) {
++        TRACE_FAST_CCACHE_CONFIG(context);
++        state->fast_state_flags |= KRB5INT_FAST_DO_FAST;
+     }
++
++    fast_flags = k5_gic_opt_get_fast_flags(opt);
++    if (fast_flags & KRB5_FAST_REQUIRED) {
++        TRACE_FAST_REQUIRED(context);
++        state->fast_state_flags |= KRB5INT_FAST_DO_FAST;
++    }
++
++    retval = fast_armor_ap_request(context, state, armor_ccache,
++                                   target_principal);
++    if (retval)
++        k5_prependmsg(context, retval, _("Error constructing AP-REQ armor"));
++
++cleanup:
+     if (ccache)
+         krb5_cc_close(context, ccache);
+-    if (target_principal)
+-        krb5_free_principal(context, target_principal);
++    krb5_free_principal(context, target_principal);
++    krb5_free_data_contents(context, &config_data);
+     return retval;
+ }
+ 
+diff --git a/src/lib/krb5/krb/fast.h b/src/lib/krb5/krb/fast.h
+index 7156ea203f..1dbce2f3f0 100644
+--- a/src/lib/krb5/krb/fast.h
++++ b/src/lib/krb5/krb/fast.h
+@@ -83,7 +83,8 @@ krb5int_fast_free_state(krb5_context context,
+ krb5_error_code
+ krb5int_fast_as_armor(krb5_context context,
+                       struct krb5int_fast_request_state *state,
+-                      krb5_get_init_creds_opt *opt, krb5_kdc_req *request);
++                      krb5_get_init_creds_opt *opt,
++                      krb5_ccache auto_armor_ccache, krb5_kdc_req *request);
+ 
+ krb5_error_code
+ krb5int_fast_reply_key(krb5_context context,
+diff --git a/src/lib/krb5/krb/get_in_tkt.c b/src/lib/krb5/krb/get_in_tkt.c
+index 4b2be41e75..a0867d1284 100644
+--- a/src/lib/krb5/krb/get_in_tkt.c
++++ b/src/lib/krb5/krb/get_in_tkt.c
+@@ -537,6 +537,10 @@ krb5_init_creds_free(krb5_context context,
+     krb5_free_data_contents(context, &ctx->salt);
+     krb5_free_data_contents(context, &ctx->s2kparams);
+     krb5_free_keyblock_contents(context, &ctx->as_key);
++    krb5_init_creds_free(context, ctx->auto_armor_ctx);
++    krb5_get_init_creds_opt_free(context, ctx->auto_armor_opt);
++    if (ctx->auto_armor_ccache != NULL)
++        krb5_cc_destroy(context, ctx->auto_armor_ccache);
+     k5_json_release(ctx->cc_config_in);
+     k5_json_release(ctx->cc_config_out);
+     free(ctx);
+@@ -771,6 +775,87 @@ encts_disabled(profile_t profile, const krb5_data *realm)
+     return (ret == 0) ? bval : FALSE;
+ }
+ 
++/* Return true if auto_fast_armor is enabled for realm. */
++static krb5_boolean
++auto_fast_armor_enabled(profile_t profile, const krb5_data *realm)
++{
++    krb5_error_code ret;
++    char *realmstr;
++    int bval;
++
++    realmstr = k5memdup0(realm->data, realm->length, &ret);
++    if (realmstr == NULL)
++        return FALSE;
++    ret = profile_get_boolean(profile, KRB5_CONF_REALMS, realmstr,
++                              KRB5_CONF_AUTO_FAST_ARMOR, FALSE, &bval);
++    free(realmstr);
++    return (ret == 0) ? bval : FALSE;
++}
++
++/*
++ * Return true if ctx should first acquire FAST armor using anonymous PKINIT.
++ * This decision is primarily dependent on the auto_fast_armor config option,
++ * but we don't acquire armor if the caller passed in an armor ccache or if the
++ * state machine is already performing an anonymous PKINIT request.
++ */
++static krb5_boolean
++want_auto_armor(krb5_context context, krb5_init_creds_context ctx)
++{
++    if (k5_gic_opt_get_fast_ccache_name(ctx->opt) != NULL)
++        return FALSE;
++    if (krb5_principal_compare_any_realm(context, ctx->request->client,
++                                         krb5_anonymous_principal()))
++        return FALSE;
++    return auto_fast_armor_enabled(context->profile,
++                                   &ctx->request->client->realm);
++}
++
++/* Create a memory ccache and nested init_creds context for acquiring FAST amor
++ * via anonymous PKINIT. */
++static krb5_error_code
++begin_auto_armor(krb5_context context, krb5_init_creds_context ctx)
++{
++    krb5_error_code ret;
++    krb5_principal anon_princ = NULL;
++    const krb5_data *realm = &ctx->request->client->realm;
++
++    TRACE_INIT_CREDS_AUTO_FAST_ARMOR(context);
++
++    ret = krb5_cc_new_unique(context, "MEMORY", NULL, &ctx->auto_armor_ccache);
++    if (ret)
++        goto cleanup;
++
++    ret = krb5_build_principal_ext(context, &anon_princ,
++                                   realm->length, realm->data,
++                                   strlen(KRB5_WELLKNOWN_NAMESTR),
++                                   KRB5_WELLKNOWN_NAMESTR,
++                                   strlen(KRB5_ANONYMOUS_PRINCSTR),
++                                   KRB5_ANONYMOUS_PRINCSTR, 0);
++    if (ret)
++        goto cleanup;
++    anon_princ->type = KRB5_NT_WELLKNOWN;
++
++    ret = krb5_get_init_creds_opt_alloc(context, &ctx->auto_armor_opt);
++    if (ret)
++        goto cleanup;
++    krb5_get_init_creds_opt_set_anonymous(ctx->auto_armor_opt, 1);
++    krb5_get_init_creds_opt_set_tkt_life(ctx->auto_armor_opt, 60 * 60);
++    ret = krb5_get_init_creds_opt_set_out_ccache(context, ctx->auto_armor_opt,
++                                                 ctx->auto_armor_ccache);
++    if (ret)
++        goto cleanup;
++
++    ret = krb5_init_creds_init(context, anon_princ, NULL, NULL,
++                               ctx->start_time, ctx->auto_armor_opt,
++                               &ctx->auto_armor_ctx);
++    if (ret)
++        goto cleanup;
++
++cleanup:
++    krb5_free_principal(context, anon_princ);
++    return ret;
++}
++
+ /**
+  * Throw away any pre-authentication realm state and begin with a
+  * unauthenticated or optimistically authenticated request.  If fast_upgrade is
+@@ -827,7 +912,7 @@ restart_init_creds_loop(krb5_context context, krb5_init_creds_context ctx,
+         goto cleanup;
+ 
+     code = krb5int_fast_as_armor(context, ctx->fast_state, ctx->opt,
+-                                 ctx->request);
++                                 ctx->auto_armor_ccache, ctx->request);
+     if (code != 0)
+         goto cleanup;
+     /* give the preauth plugins a chance to prep the request body */
+@@ -1043,6 +1128,12 @@ krb5_init_creds_init(krb5_context context,
+         ctx->request->client->type = KRB5_NT_WELLKNOWN;
+     }
+ 
++    if (want_auto_armor(context, ctx)) {
++        code = begin_auto_armor(context, ctx);
++        if (code)
++            goto cleanup;
++    }
++
+     *pctx = ctx;
+     ctx = NULL;
+ 
+@@ -1894,7 +1985,23 @@ krb5_init_creds_step(krb5_context context,
+     if (code)
+         return code;
+ 
+-    if (in->length != 0) {
++    if (ctx->auto_armor_ctx != NULL) {
++        /* Drive the nested context to acquire an anonymous TGT. */
++        code = krb5_init_creds_step(context, ctx->auto_armor_ctx, in, out,
++                                    realm, flags);
++        if (code || (*flags & KRB5_INIT_CREDS_STEP_FLAG_CONTINUE))
++            return code;
++
++        /* The nested context is complete.  Discard it to signal that the outer
++         * state machine should proceed using auto_armor_ccache. */
++        krb5_init_creds_free(context, ctx->auto_armor_ctx);
++        ctx->auto_armor_ctx = NULL;
++
++        /* Begin the actual AS request, asserting that FAST is available. */
++        code = restart_init_creds_loop(context, ctx, TRUE);
++        if (code)
++            return code;
++    } else if (in->length != 0) {
+         code = init_creds_step_reply(context, ctx, in);
+         if (code == KRB5KRB_ERR_RESPONSE_TOO_BIG) {
+             code2 = krb5int_copy_data_contents(context,
+diff --git a/src/lib/krb5/krb/init_creds_ctx.h b/src/lib/krb5/krb/init_creds_ctx.h
+index 17d55dd7c4..50be7073a5 100644
+--- a/src/lib/krb5/krb/init_creds_ctx.h
++++ b/src/lib/krb5/krb/init_creds_ctx.h
+@@ -65,6 +65,10 @@ struct _krb5_init_creds_context {
+     krb5_boolean restarted;
+     krb5_boolean fallback_disabled;
+     krb5_boolean encts_disabled;
++    /* Automatic FAST armor state machine and memory cache */
++    krb5_init_creds_context auto_armor_ctx;
++    krb5_get_init_creds_opt *auto_armor_opt;
++    krb5_ccache auto_armor_ccache;
+     struct krb5_responder_context_st rctx;
+     krb5_preauthtype selected_preauth_type;
+     krb5_preauthtype allowed_preauth_type;
+diff --git a/src/tests/gssapi/t_gssapi.py b/src/tests/gssapi/t_gssapi.py
+index 149f46d5c9..18a12d56bb 100755
+--- a/src/tests/gssapi/t_gssapi.py
++++ b/src/tests/gssapi/t_gssapi.py
+@@ -255,4 +255,22 @@ check_lifetime('actx gss_accept_sec_context', ln[7], 8000 * 86400 + 300)
+ check_lifetime('actx gss_inquire_context', ln[8], 8000 * 86400 + 300)
+ check_lifetime('actx gss_context_time', ln[9], 8000 * 86400 + 300)
+ 
++realm.stop()
++
++# Test auto_fast_armor with IAKERB driving the state machine.
++if pkinit_enabled:
++    mark('IAKERB with auto_fast_armor')
++    afa_conf = {'realms': {'$realm': {'auto_fast_armor': 'true'}}}
++    realm = K5Realm(krb5_conf=afa_conf, get_creds=False, pkinit=True)
++    realm.run([kadminl, 'modprinc', '+preauth', realm.user_princ])
++    realm.addprinc('WELLKNOWN/ANONYMOUS')
++    msgs = ('Acquiring anonymous PKINIT armor ticket for FAST',
++            'Getting initial credentials for WELLKNOWN/ANONYMOUS',
++            'Using FAST due to armor ccache negotiation result',
++            'Preauth module encrypted_challenge (138) (real) returned: 0')
++    realm.run(['./t_iakerb', 'p:' + realm.user_princ, password('user'),
++               'h:host@' + hostname, 'h:host'], expected_trace=msgs)
++else:
++    print('Skipping IAKERB auto_fast_armor test: PKINIT not built')
++
+ success('GSSAPI tests')
+diff --git a/src/tests/t_pkinit.py b/src/tests/t_pkinit.py
+index 91d4630a0a..0b6c0382ca 100755
+--- a/src/tests/t_pkinit.py
++++ b/src/tests/t_pkinit.py
+@@ -105,10 +105,6 @@ realm.kinit(realm.user_princ, password=password('user'))
+ realm.klist(realm.user_princ)
+ realm.run([kvno, realm.host_princ])
+ 
+-# Having tested password preauth, remove the keys for better error
+-# reporting.
+-realm.run([kadminl, 'purgekeys', '-all', realm.user_princ])
+-
+ # Test anonymous PKINIT.
+ mark('anonymous')
+ realm.kinit('@%s' % realm.realm, flags=['-n'], expected_code=1,
+@@ -124,6 +120,29 @@ if '97:' in out:
+ realm.run([klist, '-C'], expected_msg='start_realm = KRBTEST.COM')
+ realm.run([kvno, '-S', 'host', hostname])
+ 
++# Test auto_fast_armor.
++mark('auto_fast_armor')
++afa_conf = {'realms': {'$realm': {'auto_fast_armor': 'true'}}}
++afa_env = realm.special_env('auto_fast', False, krb5_conf=afa_conf)
++msgs = ('Acquiring anonymous PKINIT armor ticket for FAST',
++        'Getting initial credentials for WELLKNOWN/ANONYMOUS@%s' % realm.realm,
++        'Using FAST due to armor ccache negotiation result',
++        'Preauth module encrypted_challenge (138) (real) returned: 0/Success')
++realm.kinit(realm.user_princ, password=password('user'), env=afa_env,
++            expected_trace=msgs)
++realm.klist(realm.user_princ)
++
++# auto_fast_armor shouldn't trigger for direct use of anonymous PKINIT.
++mark('anonymous (auto_fast_armor=true)')
++out, trace = realm.kinit('@%s' % realm.realm, flags=['-n'], env=afa_env,
++                         return_trace=True)
++if 'Acquiring anonymous PKINIT armor ticket for FAST' in trace:
++    fail('auto_fast_armor improperly triggered for anonymous kinit')
++
++# For the remaining tests in this realm, remove the keys on user for
++# better error reporting (by preventing encrypted timestamp fallback).
++realm.run([kadminl, 'purgekeys', '-all', realm.user_princ])
++
+ # Test anonymous kadmin.
+ mark('anonymous kadmin')
+ f = open(os.path.join(realm.testdir, 'acl'), 'a')
+-- 
+2.55.0
+
+
+From 8fadc08f0719e45f57ff6391802b38bc161c3063 Mon Sep 17 00:00:00 2001
+From: Alexander Bokovoy <abokovoy@redhat.com>
+Date: Fri, 27 Mar 2026 13:48:59 +0200
+Subject: [PATCH 28/28] Relax gss_init_sec_context() proxy self check
+
+If the krb5 gss_init_sec_context() detects a proxy ccache, we check in
+get_credentials() whether the requested server principal matches the
+cache's impersonator principal.  For a host-based server name, this
+match will fail if krb5_sname_to_principal() yielded an empty realm,
+as it does in most configurations.
+
+As host-based principals generally only exist in one realm for a given
+FQDN, we can ignore the realm for this comparison when the server name
+is host-based.
+
+[ghudson@mit.edu: rewrote comment and commit message; adjusted code to
+use krb5_principal_compare_flags()]
+
+ticket: 9225 (new)
+(cherry picked from commit 473b51b640bef2e97c490d6f2985658befa89c16)
+---
+ src/lib/gssapi/krb5/init_sec_context.c | 17 ++++++++++++-----
+ 1 file changed, 12 insertions(+), 5 deletions(-)
+
+diff --git a/src/lib/gssapi/krb5/init_sec_context.c b/src/lib/gssapi/krb5/init_sec_context.c
+index 27011d0c99..208d4eefd2 100644
+--- a/src/lib/gssapi/krb5/init_sec_context.c
++++ b/src/lib/gssapi/krb5/init_sec_context.c
+@@ -124,7 +124,7 @@ get_credentials(krb5_context context, krb5_gss_cred_id_t cred,
+ {
+     krb5_error_code     code;
+     krb5_creds          in_creds, evidence_creds, mcreds, *result_creds = NULL;
+-    krb5_flags          flags = 0;
++    krb5_flags          flags = 0, cmpflag = 0;
+     krb5_principal_data server_data;
+ 
+     *out_creds = NULL;
+@@ -163,10 +163,17 @@ get_credentials(krb5_context context, krb5_gss_cred_id_t cred,
+ 
+     /* Try constrained delegation if we have proxy credentials. */
+     if (cred->impersonator != NULL) {
+-        /* If we are trying to get a ticket to ourselves, we should use the
+-         * the evidence ticket directly from cache. */
+-        if (krb5_principal_compare(context, cred->impersonator,
+-                                   server->princ)) {
++        /*
++         * If we are trying to get a ticket to the impersonator, we should use
++         * the the evidence ticket directly from the cache.  If the server name
++         * is host-based, ignore the realm for this comparison;
++         * krb5_sname_to_principal() probably yielded an empty realm, and
++         * host-based principals generally only exist in one realm.
++         */
++        if (server->princ->type == KRB5_NT_SRV_HST)
++            cmpflag = KRB5_PRINCIPAL_COMPARE_IGNORE_REALM;
++        if (krb5_principal_compare_flags(context, cred->impersonator,
++                                         server->princ, cmpflag)) {
+             flags |= KRB5_GC_CACHED;
+         } else {
+             memset(&mcreds, 0, sizeof(mcreds));
+-- 
+2.55.0
 

^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2026-09-01 14:47 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-01 14:47 [rpms/krb5] f44: GSSAPI: allow using cached S4U2Self ticket to itself Julien Rische

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox