aboutsummaryrefslogtreecommitdiff
path: root/src/lib/krb5/os/sendto_kdc.c
diff options
context:
space:
mode:
authorGreg Hudson <ghudson@mit.edu>2022-03-04 00:45:00 -0500
committerGreg Hudson <ghudson@mit.edu>2022-03-17 13:34:40 -0400
commit6297788e24cefa8f3fdd36f514e2e6569fa7b34a (patch)
tree4ed0a39b7e459c24c7dd70e8ad5fc0228f092219 /src/lib/krb5/os/sendto_kdc.c
parentcbfe46ce20f3e9265baa9c648390148c739ab830 (diff)
downloadkrb5-6297788e24cefa8f3fdd36f514e2e6569fa7b34a.zip
krb5-6297788e24cefa8f3fdd36f514e2e6569fa7b34a.tar.gz
krb5-6297788e24cefa8f3fdd36f514e2e6569fa7b34a.tar.bz2
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
Diffstat (limited to 'src/lib/krb5/os/sendto_kdc.c')
-rw-r--r--src/lib/krb5/os/sendto_kdc.c12
1 files changed, 8 insertions, 4 deletions
diff --git a/src/lib/krb5/os/sendto_kdc.c b/src/lib/krb5/os/sendto_kdc.c
index 8620ffa..0f4bf23 100644
--- a/src/lib/krb5/os/sendto_kdc.c
+++ b/src/lib/krb5/os/sendto_kdc.c
@@ -804,11 +804,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);
@@ -852,8 +855,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);