#16 Try harder to avoid password change replay errors [f34]
Merged 2 years ago by abbra. Opened 2 years ago by jrische.
rpms/ jrische/krb5 f34  into  f34

@@ -0,0 +1,91 @@ 

+ From 8c055cea87da5d27dd4b039819e79508f68e14c6 Mon Sep 17 00:00:00 2001

+ From: Greg Hudson <ghudson@mit.edu>

+ Date: Fri, 4 Mar 2022 00:45:00 -0500

+ Subject: [PATCH] Try harder to avoid password change replay errors

+ 

+ Commit d7b3018d338fc9c989c3fa17505870f23c3759a8 (ticket 7905) changed

+ change_set_password() to prefer TCP.  However, because UDP_LAST falls

+ back to UDP after one second, we can still get a replay error due to a

+ dropped packet, before the TCP layer has a chance to retry.

+ 

+ Instead, try k5_sendto() with NO_UDP, and only fall back to UDP after

+ TCP fails completely without reaching a server.  In sendto_kdc.c,

+ implement an ONLY_UDP transport strategy to allow the UDP fallback.

+ 

+ ticket: 9037

+ ---

+  src/lib/krb5/os/changepw.c   |  9 ++++++++-

+  src/lib/krb5/os/os-proto.h   |  1 +

+  src/lib/krb5/os/sendto_kdc.c | 12 ++++++++----

+  3 files changed, 17 insertions(+), 5 deletions(-)

+ 

+ diff --git a/src/lib/krb5/os/changepw.c b/src/lib/krb5/os/changepw.c

+ index 9f968da7f..c59232586 100644

+ --- a/src/lib/krb5/os/changepw.c

+ +++ b/src/lib/krb5/os/changepw.c

+ @@ -255,9 +255,16 @@ change_set_password(krb5_context context,

+      callback_info.pfn_cleanup = kpasswd_sendto_msg_cleanup;

+      krb5_free_data_contents(callback_ctx.context, &chpw_rep);

+  

+ +    /* UDP retransmits may be seen as replays.  Only try UDP after other

+ +     * transports fail completely. */

+      code = k5_sendto(callback_ctx.context, NULL, &creds->server->realm,

+ -                     &sl, UDP_LAST, &callback_info, &chpw_rep,

+ +                     &sl, NO_UDP, &callback_info, &chpw_rep,

+                       ss2sa(&remote_addr), &addrlen, NULL, NULL, NULL);

+ +    if (code == KRB5_KDC_UNREACH) {

+ +        code = k5_sendto(callback_ctx.context, NULL, &creds->server->realm,

+ +                         &sl, ONLY_UDP, &callback_info, &chpw_rep,

+ +                         ss2sa(&remote_addr), &addrlen, NULL, NULL, NULL);

+ +    }

+      if (code)

+          goto cleanup;

+  

+ diff --git a/src/lib/krb5/os/os-proto.h b/src/lib/krb5/os/os-proto.h

+ index a985f2aec..91d2791ce 100644

+ --- a/src/lib/krb5/os/os-proto.h

+ +++ b/src/lib/krb5/os/os-proto.h

+ @@ -49,6 +49,7 @@ typedef enum {

+      UDP_FIRST = 0,

+      UDP_LAST,

+      NO_UDP,

+ +    ONLY_UDP

+  } k5_transport_strategy;

+  

+  /* A single server hostname or address. */

+ diff --git a/src/lib/krb5/os/sendto_kdc.c b/src/lib/krb5/os/sendto_kdc.c

+ index 0eedec175..c7f5d861a 100644

+ --- a/src/lib/krb5/os/sendto_kdc.c

+ +++ b/src/lib/krb5/os/sendto_kdc.c

+ @@ -802,11 +802,14 @@ resolve_server(krb5_context context, const krb5_data *realm,

+      int err, result;

+      char portbuf[PORT_LENGTH];

+  

+ -    /* Skip UDP entries if we don't want UDP. */

+ +    /* Skip entries excluded by the strategy. */

+      if (strategy == NO_UDP && entry->transport == UDP)

+          return 0;

+ +    if (strategy == ONLY_UDP && entry->transport != UDP &&

+ +        entry->transport != TCP_OR_UDP)

+ +        return 0;

+  

+ -    transport = (strategy == UDP_FIRST) ? UDP : TCP;

+ +    transport = (strategy == UDP_FIRST || strategy == ONLY_UDP) ? UDP : TCP;

+      if (entry->hostname == NULL) {

+          /* Added by a module, so transport is either TCP or UDP. */

+          ai.ai_socktype = socktype_for_transport(entry->transport);

+ @@ -850,8 +853,9 @@ resolve_server(krb5_context context, const krb5_data *realm,

+      }

+  

+      /* For TCP_OR_UDP entries, add each address again with the non-preferred

+ -     * transport, unless we are avoiding UDP.  Flag these as deferred. */

+ -    if (retval == 0 && entry->transport == TCP_OR_UDP && strategy != NO_UDP) {

+ +     * transport, if there is one.  Flag these as deferred. */

+ +    if (retval == 0 && entry->transport == TCP_OR_UDP &&

+ +        (strategy == UDP_FIRST || strategy == UDP_LAST)) {

+          transport = (strategy == UDP_FIRST) ? TCP : UDP;

+          for (a = addrs; a != 0 && retval == 0; a = a->ai_next) {

+              a->ai_socktype = socktype_for_transport(transport);

+ -- 

+ 2.35.1

+ 

file modified
+6 -1
@@ -42,7 +42,7 @@ 

  Summary: The Kerberos network authentication system

  Name: krb5

  Version: 1.19.2

- Release: %{?zdpd}5%{?dist}

+ Release: %{?zdpd}6%{?dist}

  

  # rharwood has trust path to signing key and verifies on check-in

  Source0: https://web.mit.edu/kerberos/dist/krb5/%{version}/krb5-%{version}%{?dashpre}.tar.gz
@@ -93,6 +93,7 @@ 

  Patch31: Use-SHA256-instead-of-SHA1-for-PKINIT-CMS-digest.patch

  Patch32: krb5-krad-remote.patch

  Patch33: krb5-krad-larger-attrs.patch

+ Patch34: Try-harder-to-avoid-password-change-replay-errors.patch

  

  License: MIT

  URL: https://web.mit.edu/kerberos/www/
@@ -655,6 +656,10 @@ 

  %{_libdir}/libkadm5srv_mit.so.*

  

  %changelog

+ * Wed Apr 20 2022 Julien Rische <jrische@redhat.com> - 1.19.2-6

+ - Try harder to avoid password change replay errors

+ - Resolves: rhbz#2076965

+ 

  * Tue Apr 05 2022 Alexander Bokovoy <abokovoy@redhat.com> - 1.19.2-5

  - Fix libkrad client cleanup

  - Fixes rhbz#2072059

change_set_password() was changed to prefer TCP. However, because
UDP_LAST falls back to UDP after one second, we can still get a replay
error due to a dropped packet, before the TCP layer has a chance to
retry.

Instead, try k5_sendto() with NO_UDP, and only fall back to UDP after
TCP fails completely without reaching a server. In sendto_kdc.c,
implement an ONLY_UDP transport strategy to allow the UDP fallback.

Resolves: rhbz#2076965

Pull-Request has been merged by abbra

2 years ago