Bug #84091 A possible mistake in send_server_handshake_packet(sql_authentication.cc)
Submitted: 7 Dec 2016 11:59 Modified: 13 Dec 2016 14:04
Reporter: Rungong An Email Updates:
Status: Verified Impact on me:
None 
Category:MySQL Server: Pluggable Authentication Severity:S3 (Non-critical)
Version:5.7.15 OS:Any
Assigned to: CPU Architecture:Any

[7 Dec 2016 11:59] Rungong An
Description:

At line 602-611 in function send_server_handshake_packet(sql_authentication.cc):

  /* write scramble tail */
  end= (char*) memcpy(end, data + AUTH_PLUGIN_DATA_PART_1_LENGTH,
                      data_len - AUTH_PLUGIN_DATA_PART_1_LENGTH);
  end+= data_len - AUTH_PLUGIN_DATA_PART_1_LENGTH;
  end= strmake(end, plugin_name(mpvio->plugin)->str,
                    plugin_name(mpvio->plugin)->length);

  int res= protocol->write((uchar*) buff, (size_t) (end - buff + 1)) ||
           protocol->flush_net();
  DBUG_RETURN (res);

The server sends the name of server-side auth plugin name to the client. 

The client user the server-side auth plugin name to do these things:(run_plugin_auth in client.c)

  if (data_plugin && strcmp(data_plugin, auth_plugin_name))
  {
    /* data was prepared for a different plugin, don't show it to this one */
    data= 0;
    data_len= 0;
  }

  ...
  
  mpvio.cached_server_reply.pkt= (uchar*)data;
  mpvio.cached_server_reply.pkt_len= data_len;
  
  ...
  
  res= auth_plugin->authenticate_user((struct st_plugin_vio *)&mpvio, mysql);

Imagine that the auth_server and auth_client can be set as default auth plugin.

If in the server side, the .cnf file of an instance contains:

  default_authentication_plugin=auth_server

And in the client side, user the command to login:

  mysql --default_auth=auth_client -utest_user -pabc

Then the do_auth_once() will only run once and the auth will fail as

mpvio.cached_server_reply.pkt_len= data_len=0.

So sending the client-side auth plugin name to the client in function 

send_server_handshake_packet(sql_authentication.cc) may be a better choice.

How to repeat:

In 5.7.15 and 5.7.16, the value of default_authentication_plugin can only be equal to 

mysql_native_password and sha256_password. Because the client-side name and the 

server-side name of these plugins are equal, I can't repeat the description above.

Suggested fix:

change 

  end= strmake(end, plugin_name(mpvio->plugin)->str,
                    plugin_name(mpvio->plugin)->length);

to

  const char *client_auth_plugin=
    ((st_mysql_auth *) (plugin_decl(mpvio->plugin)->info))->client_auth_plugin;

  end= strmake(end, client_auth_plugin,
                    strlen(client_auth_plugin));
[13 Dec 2016 14:04] Georgi Kodinov
Thanks for taking the time to report this problem. 
This is not technically a feature request but a bug, so I'm adjusting the severity. 
Note that not all of the plugin pairs are usable as default auth. They need to follow certain pattern (the server plugin sends the first packet that should fit inside the scramble buffer and should not be larger than what the handshake packet can handle).