diff options
author | Davi Arnaut <davi.arnaut@oracle.com> | 2011-05-30 08:14:38 -0300 |
---|---|---|
committer | Davi Arnaut <davi.arnaut@oracle.com> | 2011-05-30 08:14:38 -0300 |
commit | 9f6ec599802bdb36b97780f1a7cf8c6e1293c453 (patch) | |
tree | 616bc92f691605ad3a9a16abeab4fc3ff26ddcff /sql | |
parent | f3e114291c4f02fccbd01623fd6d415328b657de (diff) | |
parent | 9b68760fd61869626808bf47ac75a9024ea662b7 (diff) | |
download | mariadb-git-9f6ec599802bdb36b97780f1a7cf8c6e1293c453.tar.gz |
Merge of mysql-5.1 into mysql-5.5.
Diffstat (limited to 'sql')
-rw-r--r-- | sql/password.c | 32 | ||||
-rw-r--r-- | sql/sql_acl.cc | 124 |
2 files changed, 116 insertions, 40 deletions
diff --git a/sql/password.c b/sql/password.c index 3b69705cc87..236e7bde0d5 100644 --- a/sql/password.c +++ b/sql/password.c @@ -205,21 +205,16 @@ void scramble_323(char *to, const char *message, const char *password) } -/* - 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. +/** + Check scrambled message. Used in pre 4.1 password handling. - RETURN VALUE - 0 - password correct - !0 - password invalid + @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 *scrambled, const char *message, { 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]); diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 44e42c86228..7ccb396b036 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -8400,14 +8400,21 @@ static bool parse_com_change_user_packet(MPVIO_EXT *mpvio, uint packet_length) } #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(MPVIO_EXT *mpvio, uint packet_length) */ 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 **buffer, *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 **buffer, @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_packet(MPVIO_EXT *mpvio, 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_packet(MPVIO_EXT *mpvio, 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_packet(MPVIO_EXT *mpvio, /* 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_packet(MPVIO_EXT *mpvio, 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] == '\'') |