diff --git a/krb5-trunk-kpasswd_tcp2.patch b/krb5-trunk-kpasswd_tcp2.patch new file mode 100644 index 0000000..b2e78c6 --- /dev/null +++ b/krb5-trunk-kpasswd_tcp2.patch @@ -0,0 +1,233 @@ +Use a list of disconnected and connected sockets to talk to kpasswd +servers, so we automatically try TCP if we fail to change the password +UDP, or if the UDP-based server is just slow. + +This patch looks big, but most of it's actually whitespace because +most of the logic is no longer called as part of a loop with UDP and +TCP being used in different iterations. RT #5868. + +Index: src/lib/krb5/os/changepw.c +=================================================================== +--- src/lib/krb5/os/changepw.c (revision 20199) ++++ src/lib/krb5/os/changepw.c (working copy) +@@ -199,14 +199,14 @@ + krb5_address remote_kaddr; + krb5_boolean useTcp = 0; + GETSOCKNAME_ARG3_TYPE addrlen; +- krb5_error_code code = 0; ++ krb5_error_code code = 0, code2 = 0; + char *code_string; +- int local_result_code; ++ int local_result_code, i; + + struct sendto_callback_context callback_ctx; + struct sendto_callback_info callback_info; + struct sockaddr_storage remote_addr; +- struct addrlist al = ADDRLIST_INIT; ++ struct addrlist al = ADDRLIST_INIT, al2 = ADDRLIST_INIT; + + memset( &callback_ctx, 0, sizeof(struct sendto_callback_context)); + callback_ctx.context = context; +@@ -225,109 +225,104 @@ + &callback_ctx.ap_req))) + goto cleanup; + +- do { +- if ((code = krb5_locate_kpasswd(callback_ctx.context, +- krb5_princ_realm(callback_ctx.context, +- creds->server), +- &al, useTcp))) +- break; +- ++ code = krb5_locate_kpasswd(callback_ctx.context, ++ krb5_princ_realm(callback_ctx.context, ++ creds->server), ++ &al, useTcp); ++ code2 = krb5_locate_kpasswd(callback_ctx.context, ++ krb5_princ_realm(callback_ctx.context, ++ creds->server), ++ &al2, !useTcp); ++ if ((al.naddrs + al2.naddrs) == 0) { ++ if (!code) ++ code = code2 ? code2 : KRB5_REALM_CANT_RESOLVE; ++ goto cleanup; ++ } ++ ++ if (al2.naddrs > 0) { ++ if (krb5int_grow_addrlist(&al, al2.naddrs)) ++ goto cleanup; ++ for (i = 0; i < al2.naddrs; i++) ++ al.addrs[al.naddrs++] = al2.addrs[i]; ++ al2.naddrs = 0; ++ } ++ +- addrlen = sizeof(remote_addr); +- +- callback_info.context = (void*) &callback_ctx; +- callback_info.pfn_callback = kpasswd_sendto_msg_callback; +- callback_info.pfn_cleanup = kpasswd_sendto_msg_cleanup; +- +- if ((code = krb5int_sendto(callback_ctx.context, +- NULL, +- &al, +- &callback_info, +- &chpw_rep, +- NULL, +- NULL, +- ss2sa(&remote_addr), +- &addrlen, +- NULL, +- NULL, +- NULL +- ))) { +- +- /* +- * Here we may want to switch to TCP on some errors. +- * right? +- */ +- break; +- } +- ++ addrlen = sizeof(remote_addr); ++ ++ callback_info.context = (void*) &callback_ctx; ++ callback_info.pfn_callback = kpasswd_sendto_msg_callback; ++ callback_info.pfn_cleanup = kpasswd_sendto_msg_cleanup; ++ ++ if ((code = krb5int_sendto(callback_ctx.context, ++ NULL, ++ &al, ++ &callback_info, ++ &chpw_rep, ++ NULL, ++ NULL, ++ ss2sa(&remote_addr), ++ &addrlen, ++ NULL, ++ NULL, ++ NULL ++ ))) ++ goto cleanup; ++ +- remote_kaddr.addrtype = ADDRTYPE_INET; +- remote_kaddr.length = sizeof(ss2sin(&remote_addr)->sin_addr); +- remote_kaddr.contents = (krb5_octet *) &ss2sin(&remote_addr)->sin_addr; +- +- if ((code = krb5_auth_con_setaddrs(callback_ctx.context, +- callback_ctx.auth_context, +- NULL, +- &remote_kaddr))) +- break; +- ++ remote_kaddr.addrtype = ADDRTYPE_INET; ++ remote_kaddr.length = sizeof(ss2sin(&remote_addr)->sin_addr); ++ remote_kaddr.contents = (krb5_octet *) &ss2sin(&remote_addr)->sin_addr; ++ ++ if ((code = krb5_auth_con_setaddrs(callback_ctx.context, ++ callback_ctx.auth_context, ++ NULL, ++ &remote_kaddr))) ++ goto cleanup; ++ +- if (set_password_for) +- code = krb5int_rd_setpw_rep(callback_ctx.context, +- callback_ctx.auth_context, +- &chpw_rep, +- &local_result_code, +- result_string); +- else +- code = krb5int_rd_chpw_rep(callback_ctx.context, +- callback_ctx.auth_context, +- &chpw_rep, +- &local_result_code, +- result_string); +- +- if (code) { +- if (code == KRB5KRB_ERR_RESPONSE_TOO_BIG && !useTcp ) { +- krb5int_free_addrlist (&al); +- useTcp = 1; +- continue; +- } +- +- break; +- } +- +- if (result_code) +- *result_code = local_result_code; +- ++ if (set_password_for) ++ code = krb5int_rd_setpw_rep(callback_ctx.context, ++ callback_ctx.auth_context, ++ &chpw_rep, ++ &local_result_code, ++ result_string); ++ else ++ code = krb5int_rd_chpw_rep(callback_ctx.context, ++ callback_ctx.auth_context, ++ &chpw_rep, ++ &local_result_code, ++ result_string); ++ ++ if (code) ++ goto cleanup; ++ ++ if (result_code) ++ *result_code = local_result_code; ++ +- if (result_code_string) { +- if (set_password_for) +- code = krb5int_setpw_result_code_string(callback_ctx.context, +- local_result_code, +- (const char **)&code_string); +- else +- code = krb5_chpw_result_code_string(callback_ctx.context, +- local_result_code, +- &code_string); +- if(code) +- goto cleanup; +- +- result_code_string->length = strlen(code_string); +- result_code_string->data = malloc(result_code_string->length); +- if (result_code_string->data == NULL) { +- code = ENOMEM; +- goto cleanup; +- } +- strncpy(result_code_string->data, code_string, result_code_string->length); +- } +- +- if (code == KRB5KRB_ERR_RESPONSE_TOO_BIG && !useTcp ) { +- krb5int_free_addrlist (&al); +- useTcp = 1; +- } else { +- break; +- } +- } while (TRUE); ++ if (result_code_string) { ++ if (set_password_for) ++ code = krb5int_setpw_result_code_string(callback_ctx.context, ++ local_result_code, ++ (const char **) &code_string); ++ else ++ code = krb5_chpw_result_code_string(callback_ctx.context, ++ local_result_code, ++ &code_string); ++ if (code) ++ goto cleanup; ++ ++ result_code_string->length = strlen(code_string); ++ result_code_string->data = malloc(result_code_string->length); ++ if (result_code_string->data == NULL) { ++ code = ENOMEM; ++ goto cleanup; ++ } ++ strncpy(result_code_string->data, code_string, result_code_string->length); ++ } + + cleanup: + if (callback_ctx.auth_context != NULL) + krb5_auth_con_free(callback_ctx.context, callback_ctx.auth_context); + ++ krb5int_free_addrlist (&al2); + krb5int_free_addrlist (&al); + krb5_free_data_contents(callback_ctx.context, &callback_ctx.ap_req); +