From cfdd330d1c0203d178b9b49932da952a41a0754f Mon Sep 17 00:00:00 2001 From: Ken Raeburn Date: Thu, 15 Jan 2009 19:15:22 +0000 Subject: [PATCH] Fix an additional multiple-write case noted by John, where sendauth calls write_message twice in a row. Add new function krb5int_write_messages, calls krb5_net_writev with multiple messages (currently only two at a time). Use it from krb5_write_message and krb5_sendauth. ticket: 6339 git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@21752 dc483132-0cff-0310-8789-dd5450dbe970 --- src/include/k5-int.h | 3 ++- src/lib/krb5/krb/sendauth.c | 29 +++++++++++++----------- src/lib/krb5/os/write_msg.c | 44 +++++++++++++++++++++++++++++-------- 3 files changed, 53 insertions(+), 23 deletions(-) diff --git a/src/include/k5-int.h b/src/include/k5-int.h index 072a4d397..78b271065 100644 --- a/src/include/k5-int.h +++ b/src/include/k5-int.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 1989,1990,1991,1992,1993,1994,1995,2000,2001, 2003,2006,2007,2008 by the Massachusetts Institute of Technology, + * Copyright (C) 1989,1990,1991,1992,1993,1994,1995,2000,2001, 2003,2006,2007,2008,2009 by the Massachusetts Institute of Technology, * Cambridge, MA, USA. All Rights Reserved. * * This software is being provided to you, the LICENSEE, by the @@ -2594,6 +2594,7 @@ krb5int_server_decrypt_ticket_keyblock krb5_error_code krb5_read_message (krb5_context, krb5_pointer, krb5_data *); krb5_error_code krb5_write_message (krb5_context, krb5_pointer, krb5_data *); +krb5_error_code krb5int_write_messages (krb5_context, krb5_pointer, krb5_data *, int); int krb5_net_read (krb5_context, int , char *, int); int krb5_net_write (krb5_context, int , const char *, int); diff --git a/src/lib/krb5/krb/sendauth.c b/src/lib/krb5/krb/sendauth.c index 5b5634307..35684bebb 100644 --- a/src/lib/krb5/krb/sendauth.c +++ b/src/lib/krb5/krb/sendauth.c @@ -1,7 +1,7 @@ /* * lib/krb5/krb/sendauth.c * - * Copyright 1991 by the Massachusetts Institute of Technology. + * Copyright 1991, 2009 by the Massachusetts Institute of Technology. * All Rights Reserved. * * Export of this software from the United States of America may @@ -38,14 +38,19 @@ static const char sendauth_version[] = "KRB5_SENDAUTH_V1.0"; krb5_error_code KRB5_CALLCONV -krb5_sendauth(krb5_context context, krb5_auth_context *auth_context, krb5_pointer fd, char *appl_version, krb5_principal client, krb5_principal server, krb5_flags ap_req_options, krb5_data *in_data, krb5_creds *in_creds, krb5_ccache ccache, krb5_error **error, krb5_ap_rep_enc_part **rep_result, krb5_creds **out_creds) +krb5_sendauth(krb5_context context, krb5_auth_context *auth_context, + krb5_pointer fd, char *appl_version, krb5_principal client, + krb5_principal server, krb5_flags ap_req_options, + krb5_data *in_data, krb5_creds *in_creds, krb5_ccache ccache, + krb5_error **error, krb5_ap_rep_enc_part **rep_result, + krb5_creds **out_creds) { krb5_octet result; krb5_creds creds; krb5_creds * credsp = NULL; krb5_creds * credspout = NULL; krb5_error_code retval = 0; - krb5_data inbuf, outbuf; + krb5_data inbuf, outbuf[2]; int len; krb5_ccache use_ccache = 0; @@ -58,13 +63,11 @@ krb5_sendauth(krb5_context context, krb5_auth_context *auth_context, krb5_pointe * over the length of the application version strings followed * by the string itself. */ - outbuf.length = strlen(sendauth_version) + 1; - outbuf.data = (char *) sendauth_version; - if ((retval = krb5_write_message(context, fd, &outbuf))) - return(retval); - outbuf.length = strlen(appl_version) + 1; - outbuf.data = appl_version; - if ((retval = krb5_write_message(context, fd, &outbuf))) + outbuf[0].length = strlen(sendauth_version) + 1; + outbuf[0].data = (char *) sendauth_version; + outbuf[1].length = strlen(appl_version) + 1; + outbuf[1].data = appl_version; + if ((retval = krb5int_write_messages(context, fd, outbuf, 2))) return(retval); /* * Now, read back a byte: 0 means no error, 1 means bad sendauth @@ -154,15 +157,15 @@ krb5_sendauth(krb5_context context, krb5_auth_context *auth_context, krb5_pointe if ((retval = krb5_mk_req_extended(context, auth_context, ap_req_options, in_data, credsp, - &outbuf))) + &outbuf[0]))) goto error_return; /* * First write the length of the AP_REQ message, then write * the message itself. */ - retval = krb5_write_message(context, fd, &outbuf); - free(outbuf.data); + retval = krb5_write_message(context, fd, &outbuf[0]); + free(outbuf[0].data); if (retval) goto error_return; diff --git a/src/lib/krb5/os/write_msg.c b/src/lib/krb5/os/write_msg.c index 86b9275d7..7586c9b86 100644 --- a/src/lib/krb5/os/write_msg.c +++ b/src/lib/krb5/os/write_msg.c @@ -31,18 +31,44 @@ #include #include "os-proto.h" +/* Try to write a series of messages with as few write(v) system calls + as possible, to avoid Nagle/DelayedAck problems. Cheating here a + little -- I know the only cases we have at the moment will send one + or two messages in a call. Sending more will work, but not as + efficiently. */ krb5_error_code -krb5_write_message(krb5_context context, krb5_pointer fdp, krb5_data *outbuf) +krb5int_write_messages(krb5_context context, krb5_pointer fdp, krb5_data *outbuf, int nbufs) { - krb5_int32 len; - int fd = *( (int *) fdp); - sg_buf sg[2]; + int fd = *( (int *) fdp); + + while (nbufs) { + int nbufs1; + sg_buf sg[4]; + krb5_int32 len[2]; - len = htonl(outbuf->length); - SG_SET(&sg[0], &len, 4); - SG_SET(&sg[1], outbuf->data, outbuf->length); - if (krb5int_net_writev(context, fd, sg, 2) < 0) { + if (nbufs > 1) + nbufs1 = 2; + else + nbufs1 = 1; + len[0] = htonl(outbuf[0].length); + SG_SET(&sg[0], &len[0], 4); + SG_SET(&sg[1], outbuf[0].data, outbuf[0].length); + if (nbufs1 == 2) { + len[1] = htonl(outbuf[1].length); + SG_SET(&sg[2], &len[1], 4); + SG_SET(&sg[3], outbuf[1].data, outbuf[1].length); + } + if (krb5int_net_writev(context, fd, sg, nbufs1 * 2) < 0) { return errno; } - return(0); + outbuf += nbufs1; + nbufs -= nbufs1; + } + return(0); +} + +krb5_error_code +krb5_write_message(krb5_context context, krb5_pointer fdp, krb5_data *outbuf) +{ + return krb5int_write_messages(context, fdp, outbuf, 1); } -- 2.26.2