diff options
author | Georgi Kodinov <Georgi.Kodinov@Oracle.com> | 2011-06-06 16:17:58 +0300 |
---|---|---|
committer | Georgi Kodinov <Georgi.Kodinov@Oracle.com> | 2011-06-06 16:17:58 +0300 |
commit | 54729bbc60045fa86d0a2a2bcc0119fb9da204f5 (patch) | |
tree | e7595cefaa0afdcedf56e8168738706d0b83f841 /sql/sql_acl.cc | |
parent | dfd4dd67c5e27865035702ddce998eaebf285381 (diff) | |
parent | ec8b38b7bd6762164c268f84489dc7ea538feb77 (diff) | |
download | mariadb-git-54729bbc60045fa86d0a2a2bcc0119fb9da204f5.tar.gz |
merged mysql-5.5->mysql-5.5-security
Diffstat (limited to 'sql/sql_acl.cc')
-rw-r--r-- | sql/sql_acl.cc | 144 |
1 files changed, 109 insertions, 35 deletions
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 7d7595899d7..a065d8f9219 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -2273,13 +2273,12 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo, */ else if (!password_len && !combo.plugin.length && no_auto_create) { - my_error(ER_PASSWORD_NO_MATCH, MYF(0), combo.user.str, combo.host.str); + my_error(ER_PASSWORD_NO_MATCH, MYF(0)); goto end; } else if (!can_create_user) { - my_error(ER_CANT_CREATE_USER_WITH_GRANT, MYF(0), - thd->security_ctx->user, thd->security_ctx->host_or_ip); + my_error(ER_CANT_CREATE_USER_WITH_GRANT, MYF(0)); goto end; } else if (combo.plugin.str[0]) @@ -2307,8 +2306,8 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo, /* what == 'N' means revoke */ if (combo.plugin.length && what != 'N') { - my_error(ER_GRANT_PLUGIN_USER_EXISTS, MYF(0), combo.user.length, - combo.user.str); + my_error(ER_GRANT_PLUGIN_USER_EXISTS, MYF(0), + static_cast<int>(combo.user.length), combo.user.str); goto end; } if (combo.password.str) // If password given @@ -3642,6 +3641,7 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list, { // Should never happen /* Restore the state of binlog format */ DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row()); + thd->lex->restore_backup_query_tables_list(&backup); if (save_binlog_row_based) thd->set_current_stmt_binlog_format_row(); DBUG_RETURN(TRUE); /* purecov: deadcode */ @@ -8398,14 +8398,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 @@ -8416,9 +8423,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); @@ -8428,7 +8435,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; } @@ -8439,7 +8499,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. @@ -8525,14 +8585,14 @@ static ulong parse_client_handshake_packet(MPVIO_EXT *mpvio, DBUG_PRINT("info", ("client capabilities: %lu", mpvio->client_capabilities)); if (mpvio->client_capabilities & CLIENT_SSL) { - char error_string[1024] __attribute__((unused)); + unsigned long errptr; /* Do the SSL layering. */ if (!ssl_acceptor_fd) return packet_error; DBUG_PRINT("info", ("IO layer change in progress...")); - if (sslaccept(ssl_acceptor_fd, net->vio, net->read_timeout)) + if (sslaccept(ssl_acceptor_fd, net->vio, net->read_timeout, &errptr)) { DBUG_PRINT("error", ("Failed to accept new SSL connection")); return packet_error; @@ -8555,7 +8615,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 @@ -8564,8 +8637,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; @@ -8590,8 +8662,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) @@ -8602,40 +8673,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] == '\'') @@ -8898,7 +8972,7 @@ err: if (mpvio->status == MPVIO_EXT::FAILURE) { inc_host_errors(mpvio->ip); - my_error(ER_HANDSHAKE_ERROR, MYF(0), mpvio->auth_info.host_or_ip); + my_error(ER_HANDSHAKE_ERROR, MYF(0)); } DBUG_RETURN(-1); } @@ -9484,7 +9558,7 @@ static int native_password_authenticate(MYSQL_PLUGIN_VIO *vio, } inc_host_errors(mpvio->ip); - my_error(ER_HANDSHAKE_ERROR, MYF(0), mpvio->auth_info.host_or_ip); + my_error(ER_HANDSHAKE_ERROR, MYF(0)); DBUG_RETURN(CR_ERROR); } @@ -9538,7 +9612,7 @@ static int old_password_authenticate(MYSQL_PLUGIN_VIO *vio, } inc_host_errors(mpvio->ip); - my_error(ER_HANDSHAKE_ERROR, MYF(0), mpvio->auth_info.host_or_ip); + my_error(ER_HANDSHAKE_ERROR, MYF(0)); return CR_ERROR; } |