CONC-783 Fix potential loss of "Proxy header not accepted from host" error

Send the proxy header and handshake response in a single write.

If the client uses two separate send() calls, the server's error message
"Proxy header not accepted from host" may be lost. This occurs because
the server sends a TCP RST (reset) instead of a FIN if it closes the socket
while the client is still sending data.

As a result, the client may receive ECONNRESET or EPIPE, without seeing
the actual error from the server.
This commit is contained in:
Vladislav Vaintroub
2025-07-18 16:02:16 +02:00
parent 77bdf5a572
commit c71865eca4
4 changed files with 13 additions and 13 deletions

View File

@ -413,6 +413,7 @@ void ma_net_end(NET *net);
void ma_net_clear(NET *net);
int ma_net_flush(NET *net);
int ma_net_write(NET *net,const unsigned char *packet, size_t len);
int ma_net_write_buff(NET *net, const char *packet, size_t len);
int ma_net_write_command(NET *net,unsigned char command,const char *packet,
size_t len, my_bool disable_flush);
int ma_net_real_write(NET *net,const char *packet, size_t len);

View File

@ -73,7 +73,7 @@ ulong net_buffer_length= 8192; /* Default length. Enlarged if necessary */
** can't normally do this the client should have a bigger max-buffer.
*/
static int ma_net_write_buff(NET *net,const char *packet, size_t len);
int ma_net_write_buff(NET *net,const char *packet, size_t len);
/* Init with packet info */
@ -246,7 +246,7 @@ int ma_net_write_command(NET *net, uchar command,
}
static int ma_net_write_buff(NET *net,const char *packet, size_t len)
int ma_net_write_buff(NET *net,const char *packet, size_t len)
{
size_t left_length;

View File

@ -1783,17 +1783,6 @@ restart:
goto error;
}
if (mysql->options.extension && mysql->options.extension->proxy_header)
{
char *hdr = mysql->options.extension->proxy_header;
size_t len = mysql->options.extension->proxy_header_len;
if (ma_pvio_write(pvio, (unsigned char *)hdr, len) <= 0)
{
ma_pvio_close(pvio);
goto error;
}
}
if (ma_net_init(net, pvio))
{
ma_pvio_close(pvio);

View File

@ -208,6 +208,11 @@ static int send_client_reply_packet(MCPVIO_EXT *mpvio,
char *buff, *end;
size_t conn_attr_len= (mysql->options.extension) ?
mysql->options.extension->connect_attrs_len : 0;
size_t proxy_header_len= 0;
char *proxy_header=
(mysql->options.extension) ? mysql->options.extension->proxy_header : NULL;
if (proxy_header)
proxy_header_len= mysql->options.extension->proxy_header_len;
/* see end= buff+32 below, fixed size of the packet is 32 bytes */
buff= malloc(33 + USERNAME_LENGTH + data_len + NAME_LEN + NAME_LEN + conn_attr_len + 9);
@ -340,6 +345,9 @@ static int send_client_reply_packet(MCPVIO_EXT *mpvio,
Send mysql->client_flag, max_packet_size - unencrypted otherwise
the server does not know we want to do SSL
*/
if (proxy_header_len)
ma_net_write_buff(net, proxy_header, proxy_header_len);
if (ma_net_write(net, (unsigned char *)buff, (size_t) (end-buff)) || ma_net_flush(net))
{
my_set_error(mysql, CR_SERVER_LOST, SQLSTATE_UNKNOWN,
@ -417,6 +425,8 @@ static int send_client_reply_packet(MCPVIO_EXT *mpvio,
*end++= compression_level;
}
if (proxy_header_len)
ma_net_write_buff(net, proxy_header, proxy_header_len);
/* Write authentication package */
if (ma_net_write(net, (unsigned char *)buff, (size_t) (end-buff)) || ma_net_flush(net))
{