mysql Source Analysis mysql Authentication Phase Roaming

Posted by jerr0 on Sat, 01 Jun 2019 23:43:59 +0200

client initiates a connection request, shakes hands three times and exchanges validation information. How does mysql complete the validation work during this period?

Process (three handshakes)

How information is encrypted

client:

hash_stage1 = sha1(password)
hash_stage2 = sha1(hash_stage1)
reply = sha1(scramble, hash_stage2) ^ hash_stage1

server: (Logic is located in sql/password.c:check_scramble_sha1, also mentioned below)

// In the mysql.user table, passwd corresponding to user is actually hash_stage 2
res1 = sha1(scramble, hash_stage2)
hash_stage1 = reply ^ res1
hash_stage2_reassured = sha1(hash_stage1)
Then, whether hash_stage 2_reassured== hash_stage 2 (from mysql. user) is consistent is used to determine whether it is legal or not.

Functions involved

As shown in the figure, client initiates connection requests, server creates new threads, and enters acl_authenticate(5.7 in sql/auth/sql_authentication.cc, 5.6 in sql/sql_acl.cc) function to complete information verification, and updates the information read out in the package to this thread.

Process Stack:

#0  parse_client_handshake_packet 
#1  server_mpvio_read_packet 
#2  native_password_authenticate
#3  do_auth_once 
#4  acl_authenticate 
#5  check_connection 
#6  login_connection 
#7  thd_prepare_connection
#8  do_handle_one_connection

Next, let's look at what has been done in these functions.
check_connection(sql/sql_connect.cc)
When receiving the client's request to build a connection, enter check_connection and first analyze the context of the connection itself (socket, tcp/ip v4/6 wo, etc.)
Of course, if you connect with very long host, it will be cut off here to prevent overflow.
Illegal ip/host will also return directly here, and if the environment is ok, it will go into the logic of acl_authenticate.
acl_authenticate:
Initialize MPVIO_EXT to save the context of the validation process; Character Set, Challenge Code,... The pit, lock, assign according to command, (new link is COM_CONNECT)

COM_CONNECT will enter the function do_auth_once(), and the return value directly determines whether the handshake is successful or not.
Let's make a judgment on authentication plugin first. Let's base our judgment on "mysql_native_password"

if (plugin)
  {
    st_mysql_auth *auth= (st_mysql_auth *) plugin_decl(plugin)->info;
    res= auth->authenticate_user(mpvio, &mpvio->auth_info);  
    ...

When mysql_native_password enters the native_password_authenticate logic:

  /* generate the scramble, or reuse the old one */
  if (mpvio->scramble[SCRAMBLE_LENGTH])
    create_random_string(mpvio->scramble, SCRAMBLE_LENGTH, mpvio->rand);

  /* send it to the client */
  if (mpvio->write_packet(mpvio, (uchar*) mpvio->scramble, SCRAMBLE_LENGTH + 1)) 
    DBUG_RETURN(CR_AUTH_HANDSHAKE);

  /* read the reply with the encrypted password */
  if ((pkt_len= mpvio->read_packet(mpvio, &pkt)) < 0)                                                                                        
    DBUG_RETURN(CR_AUTH_HANDSHAKE);
  DBUG_PRINT("info", ("reply read : pkt_len=%d", pkt_len));

So the challenge code is generated here and sent to the client, then mpvio - > read_package is called to wait for the client to return the package.
Enter server_mpvio_read_packet,
The implementation here calls the common my_net_read package.
When we get the auth package, we logically assign it to parse_client_handshake_packet to parse the contents of the package. Here, according to different client protocol s, we remove the end and end, and decide whether the client has ssl or not.

  if (mpvio->client_capabilities & CLIENT_SECURE_CONNECTION)                                                                                 
  {
    /*    
      Get the password field.
    */
    passwd= get_length_encoded_string(&end, &bytes_remaining_in_packet,
                                      &passwd_len);
  }
  else  
  {
    /*    
      Old passwords are zero terminatedtrings.
    */
    passwd= get_string(&end, &bytes_remaining_in_packet, &passwd_len);
  }
  ...

After getting the encrypted string sent by client (though called passwd), it is temporarily stored in memory and returns native_password_authenticate.
When it is decided that password check ing is necessary (in case someone does not set a password), the password is verified by entering check_scramble.

// Encrypted information in server decode Backpack
// Wrap the three formulas mentioned above in a function
my_bool
check_scramble_sha1(const uchar *scramble_arg, const char *message,
                    const uint8 *hash_stage2)
{
  uint8 buf[SHA1_HASH_SIZE];
  uint8 hash_stage2_reassured[SHA1_HASH_SIZE];

  /* create key to encrypt scramble */
  compute_sha1_hash_multi(buf, message, SCRAMBLE_LENGTH,
                          (const char *) hash_stage2, SHA1_HASH_SIZE);
  /* encrypt scramble */
  my_crypt((char *) buf, buf, scramble_arg, SCRAMBLE_LENGTH);

  /* now buf supposedly contains hash_stage1: so we can get hash_stage2 */
  compute_sha1_hash(hash_stage2_reassured, (const char *) buf, SHA1_HASH_SIZE);

  return MY_TEST(memcmp(hash_stage2, hash_stage2_reassured, SHA1_HASH_SIZE));
}

native_password_authenticate gets the return value of check_scamble and returns OK.
Return to acl_authenticate, talk about updating environment information in mpvio to threading information THD, successful login~

So you can change this code to do something, password or something, permission or something.................................................. .
Let me just say, don't take it seriously.

Topics: SHA1 SQL MySQL socket