2525#include < mysql.h>
2626#include < sql_common.h>
2727#include < welcome_copyright_notice.h> /* ORACLE_WELCOME_COPYRIGHT_NOTICE */
28+ #include < mysqld_error.h> /* to check server error codes */
2829
2930#define ADMIN_VERSION " 8.42"
3031#define MAX_MYSQL_VAR 512
@@ -625,7 +626,8 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
625626
626627 for (; argc > 0 ; argv++,argc--)
627628 {
628- switch (find_type (argv[0 ],&command_typelib, FIND_TYPE_BASIC )) {
629+ int option;
630+ switch (option= find_type (argv[0 ], &command_typelib, FIND_TYPE_BASIC )) {
629631 case ADMIN_CREATE :
630632 {
631633 char buff[FN_REFLEN +20 ];
@@ -939,6 +941,11 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
939941 char buff[128 ],crypted_pw[64 ];
940942 time_t start_time;
941943 char *typed_password= NULL , *verified= NULL ;
944+ bool log_off= true , err= false ;
945+ int retry_count= 0 ; /* Attempts to SET PASSWORD */
946+
947+ bool old= (option == ADMIN_OLD_PASSWORD );
948+
942949 /* Do initialization the same way as we do in mysqld */
943950 start_time=time ((time_t *) 0 );
944951 randominit (&rand_st,(ulong) start_time,(ulong) start_time/2 );
@@ -956,16 +963,15 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
956963 if (strcmp (typed_password, verified) != 0 )
957964 {
958965 my_printf_error (0 ," Passwords don't match" ,MYF (ME_BELL ));
959- return -1 ;
966+ err= true ;
967+ goto error;
960968 }
961969 }
962970 else
963971 typed_password= argv[1 ];
964972
965973 if (typed_password[0 ])
966974 {
967- bool old= (find_type (argv[0 ], &command_typelib, FIND_TYPE_BASIC ) ==
968- ADMIN_OLD_PASSWORD );
969975#ifdef __WIN__
970976 size_t pw_len= strlen (typed_password);
971977 if (pw_len > 1 && typed_password[0 ] == ' \' ' &&
@@ -974,16 +980,23 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
974980 " your command\n line client, as you might have expected.\n " );
975981#endif
976982 /*
977- If we don't already know to use an old-style password, see what
978- the server is using
983+ If we don't already know to use an old-style password, see
984+ (if possible) what the server is using.
979985 */
980986 if (!old)
981987 {
982988 if (mysql_query (mysql, " SHOW VARIABLES LIKE 'old_passwords'" ))
983989 {
984- my_printf_error (0 , " Could not determine old_passwords setting from server; error: '%s'" ,
985- error_flags, mysql_error (mysql));
986- return -1 ;
990+ bool fatal= (mysql_errno (mysql) != ER_MUST_CHANGE_PASSWORD );
991+ if (fatal || opt_verbose)
992+ my_printf_error (0 , " Could not determine old_passwords setting "
993+ " from server; error: '%s'." , error_flags,
994+ mysql_error (mysql));
995+ if (fatal)
996+ {
997+ err= true ;
998+ goto error;
999+ }
9871000 }
9881001 else
9891002 {
@@ -992,42 +1005,64 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
9921005 {
9931006 my_printf_error (0 ,
9941007 " Could not get old_passwords setting from "
995- " server; error: '%s'" ,
996- error_flags, mysql_error (mysql));
997- return -1 ;
1008+ " server; error: '%s'." ,
1009+ error_flags, mysql_error (mysql));
1010+ err= true ;
1011+ goto error;
9981012 }
9991013 if (!mysql_num_rows (res))
10001014 old= 1 ;
10011015 else
10021016 {
10031017 MYSQL_ROW row= mysql_fetch_row (res);
1004- old= !strncmp (row[1 ], " ON" , 2 );
1018+ old= ( !strncmp (row[1 ], " ON" , 2 ) || ! strncmp (row[ 1 ], " 1 " , 1 ) );
10051019 }
10061020 mysql_free_result (res);
10071021 }
10081022 }
1023+ /* turn logging off if we can */
1024+ if (mysql_query (mysql," set sql_log_off=1" ))
1025+ {
1026+ if (opt_verbose)
1027+ fprintf (stderr, " Note: Can't turn off logging; '%s'" , mysql_error (mysql));
1028+ log_off= false ;
1029+ }
1030+
1031+ retry:
1032+ /*
1033+ In case the password_expired flag is set ('Y'), then there is no way
1034+ to determine the password format. So, we first try to set the
1035+ password using native format. If it fails with ER_PASSWORD_LENGTH,
1036+ we will give one more try with old format.
1037+ */
10091038 if (old)
10101039 make_scrambled_password_323 (crypted_pw, typed_password);
10111040 else
10121041 make_scrambled_password (crypted_pw, typed_password);
10131042 }
10141043 else
10151044 crypted_pw[0 ]=0 ; /* No password */
1016- sprintf (buff," set password='%s',sql_log_off=0" ,crypted_pw);
10171045
1018- if (mysql_query (mysql," set sql_log_off=1" ))
1019- {
1020- my_printf_error (0 , " Can't turn off logging; error: '%s'" ,
1021- error_flags, mysql_error (mysql));
1022- return -1 ;
1023- }
1046+ sprintf (buff, " set password='%s'" , crypted_pw);
1047+
10241048 if (mysql_query (mysql,buff))
10251049 {
1050+ if ((mysql_errno (mysql) == ER_PASSWD_LENGTH ) &&
1051+ !(option == ADMIN_OLD_PASSWORD ) && !retry_count)
1052+ {
1053+ /* Try to set the password using old format. */
1054+ memset (crypted_pw, 0 , 64 );
1055+ old= 0 ;
1056+ retry_count ++;
1057+ goto retry;
1058+ }
1059+
10261060 if (mysql_errno (mysql)!=1290 )
10271061 {
10281062 my_printf_error (0 ," unable to change password; error: '%s'" ,
10291063 error_flags, mysql_error (mysql));
1030- return -1 ;
1064+ err= true ;
1065+ goto error;
10311066 }
10321067 else
10331068 {
@@ -1041,15 +1076,25 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
10411076 " --skip-grant-tables).\n "
10421077 " Use: \" mysqladmin flush-privileges password '*'\" "
10431078 " instead" , error_flags);
1044- return -1 ;
1079+ err= true ;
1080+ goto error;
10451081 }
10461082 }
1083+ if (log_off && mysql_query (mysql, " set sql_log_off=0" ))
1084+ {
1085+ if (opt_verbose)
1086+ fprintf (stderr, " Note: Can't turn on logging; '%s'" , mysql_error (mysql));
1087+ }
1088+ error:
10471089 /* free up memory from prompted password */
10481090 if (typed_password != argv[1 ])
10491091 {
10501092 my_free (typed_password);
10511093 my_free (verified);
10521094 }
1095+ if (err)
1096+ return -1 ;
1097+
10531098 argc--; argv++;
10541099 break ;
10551100 }
0 commit comments