|
|
749169 |
From aa346834947ef65c293a29300b0f98b1825d8508 Mon Sep 17 00:00:00 2001
|
|
|
dad97c |
From: Robbie Harwood <rharwood@redhat.com>
|
|
|
dad97c |
Date: Mon, 8 Oct 2018 16:02:12 -0400
|
|
|
dad97c |
Subject: [PATCH] Prefer TCP to UDP for password changes
|
|
|
dad97c |
|
|
|
dad97c |
When password changes are performed over UDP, spotty networks may
|
|
|
dad97c |
cause the client to retransmit. This leads to replay errors if the
|
|
|
dad97c |
kpasswd server receives both requests, which hide the actual request
|
|
|
dad97c |
status and make it appear that the password has not been changed, when
|
|
|
dad97c |
it may in fact have been. Use TCP instead with UDP fallback to avoid
|
|
|
dad97c |
this issue.
|
|
|
dad97c |
|
|
|
dad97c |
ticket: 7905
|
|
|
dad97c |
(cherry picked from commit d7b3018d338fc9c989c3fa17505870f23c3759a8)
|
|
|
dad97c |
---
|
|
|
dad97c |
src/lib/krb5/os/changepw.c | 110 ++++++++++++++-----------------------
|
|
|
dad97c |
1 file changed, 42 insertions(+), 68 deletions(-)
|
|
|
dad97c |
|
|
|
dad97c |
diff --git a/src/lib/krb5/os/changepw.c b/src/lib/krb5/os/changepw.c
|
|
|
dad97c |
index e4db57084..9f968da7f 100644
|
|
|
dad97c |
--- a/src/lib/krb5/os/changepw.c
|
|
|
dad97c |
+++ b/src/lib/krb5/os/changepw.c
|
|
|
dad97c |
@@ -59,13 +59,12 @@ struct sendto_callback_context {
|
|
|
dad97c |
|
|
|
dad97c |
static krb5_error_code
|
|
|
dad97c |
locate_kpasswd(krb5_context context, const krb5_data *realm,
|
|
|
dad97c |
- struct serverlist *serverlist, krb5_boolean no_udp)
|
|
|
dad97c |
+ struct serverlist *serverlist)
|
|
|
dad97c |
{
|
|
|
dad97c |
krb5_error_code code;
|
|
|
dad97c |
|
|
|
dad97c |
code = k5_locate_server(context, realm, serverlist, locate_service_kpasswd,
|
|
|
dad97c |
- no_udp);
|
|
|
dad97c |
-
|
|
|
dad97c |
+ FALSE);
|
|
|
dad97c |
if (code == KRB5_REALM_CANT_RESOLVE || code == KRB5_REALM_UNKNOWN) {
|
|
|
dad97c |
code = k5_locate_server(context, realm, serverlist,
|
|
|
dad97c |
locate_service_kadmin, TRUE);
|
|
|
dad97c |
@@ -76,7 +75,7 @@ locate_kpasswd(krb5_context context, const krb5_data *realm,
|
|
|
dad97c |
for (i = 0; i < serverlist->nservers; i++) {
|
|
|
dad97c |
struct server_entry *s = &serverlist->servers[i];
|
|
|
dad97c |
|
|
|
dad97c |
- if (!no_udp && s->transport == TCP)
|
|
|
dad97c |
+ if (s->transport == TCP)
|
|
|
dad97c |
s->transport = TCP_OR_UDP;
|
|
|
dad97c |
if (s->hostname != NULL)
|
|
|
dad97c |
s->port = DEFAULT_KPASSWD_PORT;
|
|
|
dad97c |
@@ -214,7 +213,6 @@ change_set_password(krb5_context context,
|
|
|
dad97c |
krb5_data *result_string)
|
|
|
dad97c |
{
|
|
|
dad97c |
krb5_data chpw_rep;
|
|
|
dad97c |
- krb5_boolean no_udp = FALSE;
|
|
|
dad97c |
GETSOCKNAME_ARG3_TYPE addrlen;
|
|
|
dad97c |
krb5_error_code code = 0;
|
|
|
dad97c |
char *code_string;
|
|
|
dad97c |
@@ -246,73 +244,49 @@ change_set_password(krb5_context context,
|
|
|
dad97c |
callback_ctx.remote_seq_num = callback_ctx.auth_context->remote_seq_number;
|
|
|
dad97c |
callback_ctx.local_seq_num = callback_ctx.auth_context->local_seq_number;
|
|
|
dad97c |
|
|
|
dad97c |
- do {
|
|
|
dad97c |
- k5_transport_strategy strategy = no_udp ? NO_UDP : UDP_FIRST;
|
|
|
dad97c |
+ code = locate_kpasswd(callback_ctx.context, &creds->server->realm, &sl);
|
|
|
dad97c |
+ if (code)
|
|
|
dad97c |
+ goto cleanup;
|
|
|
dad97c |
|
|
|
dad97c |
- code = locate_kpasswd(callback_ctx.context, &creds->server->realm, &sl,
|
|
|
dad97c |
- no_udp);
|
|
|
dad97c |
+ addrlen = sizeof(remote_addr);
|
|
|
dad97c |
+
|
|
|
dad97c |
+ callback_info.data = &callback_ctx;
|
|
|
dad97c |
+ callback_info.pfn_callback = kpasswd_sendto_msg_callback;
|
|
|
dad97c |
+ callback_info.pfn_cleanup = kpasswd_sendto_msg_cleanup;
|
|
|
dad97c |
+ krb5_free_data_contents(callback_ctx.context, &chpw_rep);
|
|
|
dad97c |
+
|
|
|
dad97c |
+ code = k5_sendto(callback_ctx.context, NULL, &creds->server->realm,
|
|
|
dad97c |
+ &sl, UDP_LAST, &callback_info, &chpw_rep,
|
|
|
dad97c |
+ ss2sa(&remote_addr), &addrlen, NULL, NULL, NULL);
|
|
|
dad97c |
+ if (code)
|
|
|
dad97c |
+ goto cleanup;
|
|
|
dad97c |
+
|
|
|
dad97c |
+ code = krb5int_rd_chpw_rep(callback_ctx.context,
|
|
|
dad97c |
+ callback_ctx.auth_context,
|
|
|
dad97c |
+ &chpw_rep, &local_result_code,
|
|
|
dad97c |
+ result_string);
|
|
|
dad97c |
+
|
|
|
dad97c |
+ if (code)
|
|
|
dad97c |
+ goto cleanup;
|
|
|
dad97c |
+
|
|
|
dad97c |
+ if (result_code)
|
|
|
dad97c |
+ *result_code = local_result_code;
|
|
|
dad97c |
+
|
|
|
dad97c |
+ if (result_code_string) {
|
|
|
dad97c |
+ code = krb5_chpw_result_code_string(callback_ctx.context,
|
|
|
dad97c |
+ local_result_code,
|
|
|
dad97c |
+ &code_string);
|
|
|
dad97c |
if (code)
|
|
|
dad97c |
- break;
|
|
|
dad97c |
+ goto cleanup;
|
|
|
dad97c |
|
|
|
dad97c |
- addrlen = sizeof(remote_addr);
|
|
|
dad97c |
-
|
|
|
dad97c |
- callback_info.data = &callback_ctx;
|
|
|
dad97c |
- callback_info.pfn_callback = kpasswd_sendto_msg_callback;
|
|
|
dad97c |
- callback_info.pfn_cleanup = kpasswd_sendto_msg_cleanup;
|
|
|
dad97c |
- krb5_free_data_contents(callback_ctx.context, &chpw_rep);
|
|
|
dad97c |
-
|
|
|
dad97c |
- code = k5_sendto(callback_ctx.context, NULL, &creds->server->realm,
|
|
|
dad97c |
- &sl, strategy, &callback_info, &chpw_rep,
|
|
|
dad97c |
- ss2sa(&remote_addr), &addrlen, NULL, NULL, NULL);
|
|
|
dad97c |
- if (code) {
|
|
|
dad97c |
- /*
|
|
|
dad97c |
- * Here we may want to switch to TCP on some errors.
|
|
|
dad97c |
- * right?
|
|
|
dad97c |
- */
|
|
|
dad97c |
- break;
|
|
|
dad97c |
+ result_code_string->length = strlen(code_string);
|
|
|
dad97c |
+ result_code_string->data = malloc(result_code_string->length);
|
|
|
dad97c |
+ if (result_code_string->data == NULL) {
|
|
|
dad97c |
+ code = ENOMEM;
|
|
|
dad97c |
+ goto cleanup;
|
|
|
dad97c |
}
|
|
|
dad97c |
-
|
|
|
dad97c |
- code = krb5int_rd_chpw_rep(callback_ctx.context,
|
|
|
dad97c |
- callback_ctx.auth_context,
|
|
|
dad97c |
- &chpw_rep, &local_result_code,
|
|
|
dad97c |
- result_string);
|
|
|
dad97c |
-
|
|
|
dad97c |
- if (code) {
|
|
|
dad97c |
- if (code == KRB5KRB_ERR_RESPONSE_TOO_BIG && !no_udp) {
|
|
|
dad97c |
- k5_free_serverlist(&sl);
|
|
|
dad97c |
- no_udp = 1;
|
|
|
dad97c |
- continue;
|
|
|
dad97c |
- }
|
|
|
dad97c |
-
|
|
|
dad97c |
- break;
|
|
|
dad97c |
- }
|
|
|
dad97c |
-
|
|
|
dad97c |
- if (result_code)
|
|
|
dad97c |
- *result_code = local_result_code;
|
|
|
dad97c |
-
|
|
|
dad97c |
- if (result_code_string) {
|
|
|
dad97c |
- code = krb5_chpw_result_code_string(callback_ctx.context,
|
|
|
dad97c |
- local_result_code,
|
|
|
dad97c |
- &code_string);
|
|
|
dad97c |
- if (code)
|
|
|
dad97c |
- goto cleanup;
|
|
|
dad97c |
-
|
|
|
dad97c |
- result_code_string->length = strlen(code_string);
|
|
|
dad97c |
- result_code_string->data = malloc(result_code_string->length);
|
|
|
dad97c |
- if (result_code_string->data == NULL) {
|
|
|
dad97c |
- code = ENOMEM;
|
|
|
dad97c |
- goto cleanup;
|
|
|
dad97c |
- }
|
|
|
dad97c |
- strncpy(result_code_string->data, code_string, result_code_string->length);
|
|
|
dad97c |
- }
|
|
|
dad97c |
-
|
|
|
dad97c |
- if (code == KRB5KRB_ERR_RESPONSE_TOO_BIG && !no_udp) {
|
|
|
dad97c |
- k5_free_serverlist(&sl);
|
|
|
dad97c |
- no_udp = 1;
|
|
|
dad97c |
- } else {
|
|
|
dad97c |
- break;
|
|
|
dad97c |
- }
|
|
|
dad97c |
- } while (TRUE);
|
|
|
dad97c |
+ strncpy(result_code_string->data, code_string, result_code_string->length);
|
|
|
dad97c |
+ }
|
|
|
dad97c |
|
|
|
dad97c |
cleanup:
|
|
|
dad97c |
if (callback_ctx.auth_context != NULL)
|