diff --git a/client/insert_test.c b/client/insert_test.c index 42691df6875..d8ca71bffce 100644 --- a/client/insert_test.c +++ b/client/insert_test.c @@ -16,6 +16,7 @@ #include #include +#include "my_global.h" #include "mysql.h" #define INSERT_QUERY "insert into test (name,num) values ('item %d', %d)" diff --git a/client/select_test.c b/client/select_test.c index ee2a9192865..d7f18c0f1f0 100644 --- a/client/select_test.c +++ b/client/select_test.c @@ -19,6 +19,7 @@ #endif #include #include +#include "my_global.h" #include "mysql.h" #define SELECT_QUERY "select name from test where num = %d" diff --git a/include/mysql_com.h b/include/mysql_com.h index 3ebf9fc2120..bc273750e3a 100644 --- a/include/mysql_com.h +++ b/include/mysql_com.h @@ -97,6 +97,7 @@ enum enum_server_command #define CLIENT_IGNORE_SIGPIPE 4096 /* IGNORE sigpipes */ #define CLIENT_TRANSACTIONS 8192 /* Client knows about transactions */ #define CLIENT_PROTOCOL_41 16384 /* New 4.1 protocol */ +#define CLIENT_SECURE_CONNECTION 32768 /* New 4.1 authentication */ #define SERVER_STATUS_IN_TRANS 1 /* Transaction has started */ #define SERVER_STATUS_AUTOCOMMIT 2 /* Server in auto_commit mode */ diff --git a/sql/mysqld.cc b/sql/mysqld.cc index bf2b664f8c6..45fb7419607 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -317,6 +317,7 @@ uint volatile thread_count=0, thread_running=0, kill_cached_threads=0, ulong thd_startup_options=(OPTION_UPDATE_LOG | OPTION_AUTO_IS_NULL | OPTION_BIN_LOG | OPTION_QUOTE_SHOW_CREATE ); uint protocol_version=PROTOCOL_VERSION; +uint connection_auth_flag=0; /* Supported authentication mode */ struct system_variables global_system_variables; struct system_variables max_system_variables; ulong keybuff_size,table_cache_size, diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 2012b565dae..3b37ff552a3 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -32,6 +32,8 @@ #include #include +extern uint connection_auth_flag; + struct acl_host_and_ip { char *hostname; @@ -143,7 +145,11 @@ my_bool acl_init(bool dont_read_acl_tables) (hash_get_key) acl_entry_get_key, (void (*)(void*)) free); if (dont_read_acl_tables) + { + /* If we do not read tables use old handshake to make it quick for all clients */ + connection_auth_flag=CLIENT_LONG_PASSWORD; DBUG_RETURN(0); /* purecov: tested */ + } /* To be able to run this from boot, we allocate a temporary THD @@ -218,6 +224,7 @@ my_bool acl_init(bool dont_read_acl_tables) DBUG_PRINT("info",("user table fields: %d",table->fields)); allow_all_hosts=0; + connection_auth_flag=0; /* Reset flag as we're rereading the table */ while (!(read_record_info.read_record(&read_record_info))) { ACL_USER user; @@ -242,6 +249,18 @@ my_bool acl_init(bool dont_read_acl_tables) } get_salt_from_password(user.salt,user.password); user.pversion=get_password_version(user.password); + /* + We check the version of passwords in database. If no old passwords found we can force new handshake + if there are only old password we will force new handshake. In case of both types of passwords + found we will perform 2 stage authentication. + */ + if (user.password && user.password[0]!=0) /* empty passwords are not counted */ + { + if (user.pversion) + connection_auth_flag|=CLIENT_SECURE_CONNECTION; + else + connection_auth_flag|=CLIENT_LONG_PASSWORD; + } user.access=get_access(table,3) & GLOBAL_ACLS; user.sort=get_sort(2,user.host.hostname,user.user); user.hostname_length= (user.host.hostname ? @@ -299,7 +318,18 @@ my_bool acl_init(bool dont_read_acl_tables) sizeof(ACL_USER),(qsort_cmp) acl_compare); end_read_record(&read_record_info); freeze_size(&acl_users); - + + /* + If database is empty or has no passwords use new connection protocol + unless we're running with --old-passwords option + */ + if (!connection_auth_flag) + { + if(!opt_old_passwords) + connection_auth_flag=CLIENT_SECURE_CONNECTION; + else connection_auth_flag=CLIENT_LONG_PASSWORD; + } + printf("Set flag after read: %d\n",connection_auth_flag); init_read_record(&read_record_info,thd,table=tables[2].table,NULL,1,0); VOID(my_init_dynamic_array(&acl_dbs,sizeof(ACL_DB),50,100)); while (!(read_record_info.read_record(&read_record_info))) @@ -674,6 +704,12 @@ static void acl_update_user(const char *user, const char *host, acl_user->password=(char*) ""; // Just point at something get_salt_from_password(acl_user->salt,password); acl_user->pversion=get_password_version(acl_user->password); + // We should allow connection with authentication method matching password + if (acl_user->pversion) + connection_auth_flag|=CLIENT_SECURE_CONNECTION; + else + connection_auth_flag|=CLIENT_LONG_PASSWORD; + printf("Debug: flag set to %d\n",connection_auth_flag); } } break; @@ -1084,7 +1120,15 @@ bool change_password(THD *thd, const char *host, const char *user, if (!new_password[0]) acl_user->password=0; else - acl_user->password=(char*) ""; // Point at something + { + acl_user->password=(char*) ""; // Point at something + /* Adjust global connection options depending of client password*/ + if (acl_user->pversion) + connection_auth_flag|=CLIENT_SECURE_CONNECTION; + else + connection_auth_flag|=CLIENT_LONG_PASSWORD; + } + acl_cache->clear(1); // Clear locked hostname cache VOID(pthread_mutex_unlock(&acl_cache->lock));