krb5/krb5-trunk-kpasswd_tcp2.patch
2008-02-12 16:28:13 +00:00

234 lines
6.6 KiB
Diff

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);