List:Commits« Previous MessageNext Message »
From:Davi Arnaut Date:May 30 2011 11:14am
Subject:bzr commit into mysql-5.5 branch (davi:3411)
View as plain text  
# At a local mysql-5.5 repository of davi

 3411 Davi Arnaut	2011-05-30 [merge]
      Merge of mysql-5.1 into mysql-5.5.

    modified:
      sql/password.c
      sql/sql_acl.cc
=== modified file 'sql/password.c'
--- a/sql/password.c	2010-08-09 08:32:50 +0000
+++ b/sql/password.c	2011-05-30 11:14:38 +0000
@@ -205,21 +205,16 @@ void scramble_323(char *to, const char *
 }
 
 
-/*
-    Check scrambled message
-    Used in pre 4.1 password handling
-  SYNOPSIS
-    check_scramble_323()
-    scrambled  scrambled message to check.
-    message    original random message which was used for scrambling; must
-               be exactly SCRAMBLED_LENGTH_323 bytes long and
-               NULL-terminated.
-    hash_pass  password which should be used for scrambling
-    All params are IN.
-
-  RETURN VALUE
-    0 - password correct
-   !0 - password invalid
+/**
+  Check scrambled message. Used in pre 4.1 password handling.
+
+  @param scrambled  Scrambled message to check.
+  @param message    Original random message which was used for scrambling.
+  @param hash_pass  Password which should be used for scrambling.
+
+  @remark scrambled and message must be SCRAMBLED_LENGTH_323 bytes long.
+
+  @return FALSE if password is correct, TRUE otherwise.
 */
 
 my_bool
@@ -228,9 +223,16 @@ check_scramble_323(const unsigned char *
 {
   struct rand_struct rand_st;
   ulong hash_message[2];
-  uchar buff[16],*to,extra;                     /* Big enough for check */
+  /* Big enough for checks. */
+  uchar buff[16], scrambled_buff[SCRAMBLE_LENGTH_323 + 1];
+  uchar *to, extra;
   const uchar *pos;
 
+  /* Ensure that the scrambled message is null-terminated. */
+  memcpy(scrambled_buff, scrambled, SCRAMBLE_LENGTH_323);
+  scrambled_buff[SCRAMBLE_LENGTH_323]= '\0';
+  scrambled= scrambled_buff;
+
   hash_password(hash_message, message, SCRAMBLE_LENGTH_323);
   randominit(&rand_st,hash_pass[0] ^ hash_message[0],
              hash_pass[1] ^ hash_message[1]);

=== modified file 'sql/sql_acl.cc'
--- a/sql/sql_acl.cc	2011-05-26 12:33:21 +0000
+++ b/sql/sql_acl.cc	2011-05-30 11:14:38 +0000
@@ -8400,14 +8400,21 @@ static bool parse_com_change_user_packet
 }
 
 #ifndef EMBEDDED_LIBRARY
+
+/** Get a string according to the protocol of the underlying buffer. */
+typedef char * (*get_proto_string_func_t) (char **, size_t *, size_t *);
+
 /**
-  Get a null character terminated string from a user-supplied buffer.
+  Get a string formatted according to the 4.1 version of the MySQL protocol.
 
-  @param buffer[in, out]    Pointer to the buffer to be scanned.
+  @param buffer[in, out]    Pointer to the user-supplied buffer to be scanned.
   @param max_bytes_available[in, out]  Limit the bytes to scan.
   @param string_length[out] The number of characters scanned not including
                             the null character.
 
+  @remark Strings are always null character terminated in this version of the
+          protocol.
+
   @remark The string_length does not include the terminating null character.
           However, after the call, the buffer is increased by string_length+1
           bytes, beyond the null character if there still available bytes to
@@ -8418,9 +8425,9 @@ static bool parse_com_change_user_packet
 */
 
 static
-char *get_null_terminated_string(char **buffer,
-                                 size_t *max_bytes_available,
-                                 size_t *string_length)
+char *get_41_protocol_string(char **buffer,
+                             size_t *max_bytes_available,
+                             size_t *string_length)
 {
   char *str= (char *)memchr(*buffer, '\0', *max_bytes_available);
 
@@ -8430,7 +8437,60 @@ char *get_null_terminated_string(char **
   *string_length= (size_t)(str - *buffer);
   *max_bytes_available-= *string_length + 1;
   str= *buffer;
-  *buffer += *string_length + 1;  
+  *buffer += *string_length + 1;
+
+  return str;
+}
+
+
+/**
+  Get a string formatted according to the 4.0 version of the MySQL protocol.
+
+  @param buffer[in, out]    Pointer to the user-supplied buffer to be scanned.
+  @param max_bytes_available[in, out]  Limit the bytes to scan.
+  @param string_length[out] The number of characters scanned not including
+                            the null character.
+
+  @remark If there are not enough bytes left after the current position of
+          the buffer to satisfy the current string, the string is considered
+          to be empty and a pointer to empty_c_string is returned.
+
+  @remark A string at the end of the packet is not null terminated.
+
+  @return Pointer to beginning of the string scanned, or a pointer to a empty
+          string.
+*/
+static
+char *get_40_protocol_string(char **buffer,
+                             size_t *max_bytes_available,
+                             size_t *string_length)
+{
+  char *str;
+  size_t len;
+
+  /* No bytes to scan left, treat string as empty. */
+  if ((*max_bytes_available) == 0)
+  {
+    *string_length= 0;
+    return empty_c_string;
+  }
+
+  str= (char *) memchr(*buffer, '\0', *max_bytes_available);
+
+  /*
+    If the string was not null terminated by the client,
+    the remainder of the packet is the string. Otherwise,
+    advance the buffer past the end of the null terminated
+    string.
+  */
+  if (str == NULL)
+    len= *string_length= *max_bytes_available;
+  else
+    len= (*string_length= (size_t)(str - *buffer)) + 1;
+
+  str= *buffer;
+  *buffer+= len;
+  *max_bytes_available-= len;
 
   return str;
 }
@@ -8441,7 +8501,7 @@ char *get_null_terminated_string(char **
   @param buffer[in, out] The buffer to scan; updates position after scan.
   @param max_bytes_available[in, out] Limit the number of bytes to scan
   @param string_length[out] Number of characters scanned
-  
+
   @remark In case the length is zero, then the total size of the string is
     considered to be 1 byte; the size byte.
 
@@ -8557,7 +8617,20 @@ static ulong parse_client_handshake_pack
   if ((mpvio->client_capabilities & CLIENT_TRANSACTIONS) &&
       opt_using_transactions)
     net->return_status= mpvio->server_status;
- 
+
+  /*
+    The 4.0 and 4.1 versions of the protocol differ on how strings
+    are terminated. In the 4.0 version, if a string is at the end
+    of the packet, the string is not null terminated. Do not assume
+    that the returned string is always null terminated.
+  */
+  get_proto_string_func_t get_string;
+
+  if (mpvio->client_capabilities & CLIENT_PROTOCOL_41)
+    get_string= get_41_protocol_string;
+  else
+    get_string= get_40_protocol_string;
+
   /*
     In order to safely scan a head for '\0' string terminators
     we must keep track of how many bytes remain in the allocated
@@ -8566,8 +8639,7 @@ static ulong parse_client_handshake_pack
   size_t bytes_remaining_in_packet= pkt_len - (end - (char *)net->read_pos);
 
   size_t user_len;
-  char *user= get_null_terminated_string(&end, &bytes_remaining_in_packet,
-                                         &user_len);
+  char *user= get_string(&end, &bytes_remaining_in_packet, &user_len);
   if (user == NULL)
     return packet_error;
 
@@ -8592,8 +8664,7 @@ static ulong parse_client_handshake_pack
     /*
       Old passwords are zero terminated strings.
     */
-    passwd= get_null_terminated_string(&end, &bytes_remaining_in_packet,
-                                       &passwd_len);
+    passwd= get_string(&end, &bytes_remaining_in_packet, &passwd_len);
   }
 
   if (passwd == NULL)
@@ -8604,40 +8675,43 @@ static ulong parse_client_handshake_pack
 
   if (mpvio->client_capabilities & CLIENT_CONNECT_WITH_DB)
   {
-    db= get_null_terminated_string(&end, &bytes_remaining_in_packet,
-                                   &db_len);
+    db= get_string(&end, &bytes_remaining_in_packet, &db_len);
     if (db == NULL)
       return packet_error;
   }
 
   size_t client_plugin_len= 0;
-  char *client_plugin= get_null_terminated_string(&end,
-                                                  &bytes_remaining_in_packet,
-                                                  &client_plugin_len);
+  char *client_plugin= get_string(&end, &bytes_remaining_in_packet,
+                                  &client_plugin_len);
   if (client_plugin == NULL)
     client_plugin= &empty_c_string[0];
- 
+
   char db_buff[NAME_LEN + 1];           // buffer to store db in utf8
   char user_buff[USERNAME_LENGTH + 1];	// buffer to store user in utf8
   uint dummy_errors;
-  
 
-  /* Since 4.1 all database names are stored in utf8 */
+
+  /*
+    Copy and convert the user and database names to the character set used
+    by the server. Since 4.1 all database names are stored in UTF-8. Also,
+    ensure that the names are properly null-terminated as this is relied
+    upon later.
+  */
   if (db)
   {
     db_len= copy_and_convert(db_buff, sizeof(db_buff) - 1, system_charset_info,
                              db, db_len, mpvio->charset_adapter->charset(),
                              &dummy_errors);
+    db_buff[db_len]= '\0';
     db= db_buff;
-    db_buff[db_len]= 0;
   }
 
   user_len= copy_and_convert(user_buff, sizeof(user_buff) - 1,
-                                system_charset_info, user, user_len,
-                                mpvio->charset_adapter->charset(),
-                                &dummy_errors);
+                             system_charset_info, user, user_len,
+                             mpvio->charset_adapter->charset(),
+                             &dummy_errors);
+  user_buff[user_len]= '\0';
   user= user_buff;
-  user_buff[user_len]= 0;
 
   /* If username starts and ends in "'", chop them off */
   if (user_len > 1 && user[0] == '\'' && user[user_len - 1] == '\'')

No bundle (reason: revision is a merge (you can force generation of a bundle with env var BZR_FORCE_BUNDLE=1)).
Thread
bzr commit into mysql-5.5 branch (davi:3411) Davi Arnaut31 May