diff options
author | unknown <kostja@oak.local> | 2003-07-04 20:52:04 +0400 |
---|---|---|
committer | unknown <kostja@oak.local> | 2003-07-04 20:52:04 +0400 |
commit | ccbcf1c9da89eaee2dfb4219da1d86b6f590ac20 (patch) | |
tree | 8b19a2b1b84bfe2fb3f99f403acec7fb0a600501 /sql | |
parent | dbb088b034e19e99ec209cbbc4eed3bff64172da (diff) | |
download | mariadb-git-ccbcf1c9da89eaee2dfb4219da1d86b6f590ac20.tar.gz |
Bug fixes for authentication
OLD_PASSWORD made a keyword to allow set password=old_password('abc') constructions.
BitKeeper/etc/ignore:
Added BitKeeper/post-commit BitKeeper/post-commit-manual build_tags.sh tests/connect_test BUILD/compile-pentium-maintainer to the ignore list
include/mysql_com.h:
scramble return type changed to void as now it's not used
libmysql/libmysql.c:
fixed bug with with failed authentification when scramble contained zero byte
sql-common/client.c:
applied patch from Lycos team
fixed bug with scramble containing zero byte
sql/item_create.cc:
removed create_func_old_password, create_func_password as they are not used any more
sql/item_create.h:
removed create_func_old_password, create_func_password as they are not used any more
sql/item_strfunc.cc:
Added alloc() function to Item_func_password, Item_func_old_password, which is used in sql_yacc.yy
sql/item_strfunc.h:
Added alloc() function to Item_func_password, Item_func_old_password, which is used in sql_yacc.yy
sql/lex.h:
OLD_PASSWORD now is keyword, to allow statements like
set password=old_password('abc')
sql/password.c:
fixed scramble return value
trailing zero now is not written
sql/sql_acl.cc:
incorporated patch from Lycos team
41 replaced with constant
acl_getroot rewritten to support ER_AUTH_... error
sql/sql_parse.cc:
authenticate merged with check_user
check_user return values reversed, support for ER_AUTH in check_user.added
sql/sql_yacc.yy:
OLD_PASSWORD now is keyword, to allow statements like
set password=old_password('abc')
Diffstat (limited to 'sql')
-rw-r--r-- | sql/item_create.cc | 12 | ||||
-rw-r--r-- | sql/item_create.h | 2 | ||||
-rw-r--r-- | sql/item_strfunc.cc | 16 | ||||
-rw-r--r-- | sql/item_strfunc.h | 3 | ||||
-rw-r--r-- | sql/lex.h | 2 | ||||
-rw-r--r-- | sql/password.c | 12 | ||||
-rw-r--r-- | sql/sql_acl.cc | 9 | ||||
-rw-r--r-- | sql/sql_parse.cc | 250 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 37 |
9 files changed, 170 insertions, 173 deletions
diff --git a/sql/item_create.cc b/sql/item_create.cc index 90f42cee959..fbb26e83dfd 100644 --- a/sql/item_create.cc +++ b/sql/item_create.cc @@ -52,13 +52,6 @@ Item *create_func_ord(Item* a) return new Item_func_ord(a); } -Item *create_func_old_password(Item* a) -{ - return new Item_func_old_password(a); -} - - - Item *create_func_asin(Item* a) { return new Item_func_asin(a); @@ -332,11 +325,6 @@ Item *create_func_quarter(Item* a) return new Item_func_quarter(a); } -Item *create_func_password(Item* a) -{ - return new Item_func_password(a); -} - Item *create_func_radians(Item *a) { return new Item_func_units((char*) "radians",a,M_PI/180,0.0); diff --git a/sql/item_create.h b/sql/item_create.h index 4151f59a87f..2872451c034 100644 --- a/sql/item_create.h +++ b/sql/item_create.h @@ -69,14 +69,12 @@ Item *create_func_monthname(Item* a); Item *create_func_nullif(Item* a, Item *b); Item *create_func_oct(Item *); Item *create_func_ord(Item* a); -Item *create_func_old_password(Item* a); Item *create_func_period_add(Item* a, Item *b); Item *create_func_period_diff(Item* a, Item *b); Item *create_func_pi(void); Item *create_func_pow(Item* a, Item *b); Item *create_func_current_user(void); Item *create_func_quarter(Item* a); -Item *create_func_password(Item* a); Item *create_func_radians(Item *a); Item *create_func_release_lock(Item* a); Item *create_func_repeat(Item* a, Item *b); diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index f8488565b75..def465363fe 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -1360,6 +1360,14 @@ String *Item_func_password::val_str(String *str) return str; } +char *Item_func_password::alloc(THD *thd, const char *password) +{ + char *buff= (char *) thd->alloc(SCRAMBLED_PASSWORD_CHAR_LENGTH+1); + if (buff) + make_scrambled_password(buff, password); + return buff; +} + /* Item_func_old_password */ String *Item_func_old_password::val_str(String *str) @@ -1374,6 +1382,14 @@ String *Item_func_old_password::val_str(String *str) return str; } +char *Item_func_old_password::alloc(THD *thd, const char *password) +{ + char *buff= (char *) thd->alloc(SCRAMBLED_PASSWORD_CHAR_LENGTH_323+1); + if (buff) + make_scrambled_password_323(buff, password); + return buff; +} + #define bin_to_ascii(c) ((c)>=38?((c)-38+'a'):(c)>=12?((c)-12+'A'):(c)+'.') diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index 11f5a66b3d1..3e0239cf76a 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -270,6 +270,7 @@ public: String *val_str(String *str); void fix_length_and_dec() { max_length= SCRAMBLED_PASSWORD_CHAR_LENGTH; } const char *func_name() const { return "password"; } + static char *alloc(THD *thd, const char *password); }; @@ -288,7 +289,7 @@ public: String *val_str(String *str); void fix_length_and_dec() { max_length= SCRAMBLED_PASSWORD_CHAR_LENGTH_323; } const char *func_name() const { return "old_password"; } - unsigned int size_of() { return sizeof(*this);} + static char *alloc(THD *thd, const char *password); }; diff --git a/sql/lex.h b/sql/lex.h index bb6e7a81ab4..f105fd4d9c8 100644 --- a/sql/lex.h +++ b/sql/lex.h @@ -284,6 +284,7 @@ static SYMBOL symbols[] = { { "NULL", SYM(NULL_SYM),0,0}, { "NUMERIC", SYM(NUMERIC_SYM),0,0}, { "OFFSET", SYM(OFFSET_SYM),0,0}, + { "OLD_PASSWORD", SYM(OLD_PASSWORD),0,0}, { "ON", SYM(ON),0,0}, { "OPEN", SYM(OPEN_SYM),0,0}, { "OPTIMIZE", SYM(OPTIMIZE),0,0}, @@ -577,7 +578,6 @@ static SYMBOL sql_functions[] = { { "NUMPOINTS", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_numpoints)}, { "OCTET_LENGTH", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_length)}, { "OCT", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_oct)}, - { "OLD_PASSWORD", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_old_password)}, { "ORD", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ord)}, { "OVERLAPS", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_overlaps)}, { "PERIOD_ADD", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_period_add)}, diff --git a/sql/password.c b/sql/password.c index be6514d89c6..bfdb453af01 100644 --- a/sql/password.c +++ b/sql/password.c @@ -446,22 +446,20 @@ make_scrambled_password(char *to, const char *password) Produce an obscure octet sequence from password and random string, recieved from the server. This sequence corresponds to the password, but password can not be easily restored from it. The sequence - is then sent to the server for validation. Trailing zero is stored in - the buf. + is then sent to the server for validation. Trailing zero is not stored + in the buf as it is not needed. This function is used by client to create authenticated reply to the server's greeting. SYNOPSIS scramble() buf OUT store scrambled string here. The buf must be at least - SHA1_HASH_SIZE+1 bytes long. + SHA1_HASH_SIZE bytes long. message IN random message, must be exactly SCRAMBLE_LENGTH long and NULL-terminated. password IN users' password - RETURN VALUE - end of scrambled string */ -char * +void scramble(char *to, const char *message, const char *password) { SHA1_CONTEXT sha1_context; @@ -483,8 +481,6 @@ scramble(char *to, const char *message, const char *password) /* xor allows 'from' and 'to' overlap: lets take advantage of it */ sha1_result(&sha1_context, (uint8 *) to); my_crypt(to, (const uint8 *) to, hash_stage1, SCRAMBLE_LENGTH); - to[SHA1_HASH_SIZE]= '\0'; - return to + SHA1_HASH_SIZE; } diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index bbc6b74c3a9..f88799c2843 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -51,7 +51,7 @@ static byte* acl_entry_get_key(acl_entry *entry,uint *length, return (byte*) entry->key; } -#define ACL_KEY_LENGTH (sizeof(long)+NAME_LEN+17) +#define ACL_KEY_LENGTH (sizeof(long)+NAME_LEN+USERNAME_LENGTH+1) static DYNAMIC_ARRAY acl_hosts,acl_users,acl_dbs; static MEM_ROOT mem, memex; @@ -208,7 +208,8 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables) DBUG_PRINT("info",("user table fields: %d, password length: %d", table->fields, table->field[2]->field_length)); - if (table->field[2]->field_length < 41 && !use_old_passwords) + if (table->field[2]->field_length < SCRAMBLED_PASSWORD_CHAR_LENGTH && + !use_old_passwords) { sql_print_error("mysql.user table is not updated to new password format; " "Disabling new password usage until " @@ -516,6 +517,7 @@ static int acl_compare(ACL_ACCESS *a,ACL_ACCESS *b) RETURN VALUE 0 success: thread data and mqh are updated 1 user not found or authentification failure + 2 user found, has long (4.1.1) salt, but passwd is in old (3.23) format. -1 user found, has short (3.23) salt, but passwd is in new (4.1.1) format. */ @@ -564,6 +566,9 @@ acl_getroot(THD *thd, USER_RESOURCES *mqh, else if (passwd_len == SCRAMBLE_LENGTH && user_i->salt_len == SCRAMBLE_LENGTH_323) res= -1; + else if (passwd_len == SCRAMBLE_LENGTH_323 && + user_i->salt_len == SCRAMBLE_LENGTH) + res= 2; /* linear search complete: */ break; } diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 384ec2bd4dd..a6d3121158c 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -195,11 +195,8 @@ end: RETURN VALUE 0 OK; thd->user, thd->master_access, thd->priv_user, thd->db and thd->db_access are updated; OK is sent to client; - 1 access denied or internal error; error is sent to client - Note, that this return semantics differs from check_connection, - which returns -1 if message was already sent. - -1 acl entry for this user contains old scramble, but passwd contains - new one, error is not sent to client + -1 access denied or handshake error; error is sent to client; + >0 error, not sent to client */ static int check_user(THD *thd, enum enum_server_command command, @@ -208,87 +205,129 @@ static int check_user(THD *thd, enum enum_server_command command, { DBUG_ENTER("check_user"); + if (passwd_len != 0 && + passwd_len != SCRAMBLE_LENGTH && + passwd_len != SCRAMBLE_LENGTH_323) + DBUG_RETURN(ER_HANDSHAKE_ERROR); + /* Why this is set here? - probably to reset current DB to 'no database selected' in case of 'change user' failure. */ thd->db= 0; thd->db_length= 0; - + + char buff[NAME_LEN + 1]; /* to conditionally save db */ + USER_RESOURCES ur; int res= acl_getroot(thd, &ur, passwd, passwd_len, protocol_version == 9 || !(thd->client_capabilities & CLIENT_LONG_PASSWORD)); - if (res == 0 && !(thd->master_access & NO_ACCESS)) // authentification is OK + if (res == -1) { - DBUG_PRINT("info", - ("Capabilities: %d packet_length: %ld Host: '%s' " - "Login user: '%s' Priv_user: '%s' Using password: %s " - "Access: %u db: '%s'", - thd->client_capabilities, thd->max_client_packet_length, - thd->host_or_ip, thd->user, thd->priv_user, - passwd_len ? "yes": "no", - thd->master_access, thd->db ? thd->db : "*none*")); - - if (check_count) + /* + This happens when client (new) sends password scrambled with + scramble(), but database holds old value (scrambled with + scramble_323()). Here we please client to send scrambled_password + in old format. + */ + /* save db because network buffer is to hold new packet */ + if (db) { - VOID(pthread_mutex_lock(&LOCK_thread_count)); - bool count_ok= thread_count < max_connections + delayed_insert_threads || - thd->master_access & SUPER_ACL; - VOID(pthread_mutex_unlock(&LOCK_thread_count)); - if (!count_ok) - { // too many connections - send_error(thd, ER_CON_COUNT_ERROR); - DBUG_RETURN(1); - } + strmake(buff, db, NAME_LEN); + db= buff; + } + NET *net= &thd->net; + if (my_net_write(net, thd->scramble_323, SCRAMBLE_LENGTH_323 + 1) || + net_flush(net) || + my_net_read(net) != SCRAMBLE_LENGTH_323 + 1) // We have to read very + { // specific packet size + inc_host_errors(&thd->remote.sin_addr); + DBUG_RETURN(ER_HANDSHAKE_ERROR); } + /* Final attempt to check the user based on reply */ + /* So as passwd is short, errcode is always >= 0 */ + res= acl_getroot(thd, &ur, (char *) net->read_pos, SCRAMBLE_LENGTH_323, + false); + } + /* here res is always >= 0 */ + if (res == 0) + { + if (!(thd->master_access & NO_ACCESS)) // authentification is OK + { + DBUG_PRINT("info", + ("Capabilities: %d packet_length: %ld Host: '%s' " + "Login user: '%s' Priv_user: '%s' Using password: %s " + "Access: %u db: '%s'", + thd->client_capabilities, thd->max_client_packet_length, + thd->host_or_ip, thd->user, thd->priv_user, + passwd_len ? "yes": "no", + thd->master_access, thd->db ? thd->db : "*none*")); + + if (check_count) + { + VOID(pthread_mutex_lock(&LOCK_thread_count)); + bool count_ok= thread_count < max_connections + delayed_insert_threads + || thd->master_access & SUPER_ACL; + VOID(pthread_mutex_unlock(&LOCK_thread_count)); + if (!count_ok) + { // too many connections + send_error(thd, ER_CON_COUNT_ERROR); + DBUG_RETURN(-1); + } + } - /* Why logging is performed before all checks've passed? */ - mysql_log.write(thd,command, - (thd->priv_user == thd->user ? - (char*) "%s@%s on %s" : - (char*) "%s@%s as anonymous on %s"), - thd->user, thd->host_or_ip, - db ? db : (char*) ""); + /* Why logging is performed before all checks've passed? */ + mysql_log.write(thd,command, + (thd->priv_user == thd->user ? + (char*) "%s@%s on %s" : + (char*) "%s@%s as anonymous on %s"), + thd->user, thd->host_or_ip, + db ? db : (char*) ""); - /* Why is it set here? */ - thd->db_access=0; + /* Why is it set here? */ + thd->db_access=0; - /* Don't allow user to connect if he has done too many queries */ - if ((ur.questions || ur.updates || ur.connections) && - get_or_create_user_conn(thd,thd->user,thd->host_or_ip,&ur)) - DBUG_RETURN(1); - if (thd->user_connect && thd->user_connect->user_resources.connections && - check_for_max_user_connections(thd, thd->user_connect)) - DBUG_RETURN(1); + /* Don't allow user to connect if he has done too many queries */ + if ((ur.questions || ur.updates || ur.connections) && + get_or_create_user_conn(thd,thd->user,thd->host_or_ip,&ur)) + DBUG_RETURN(1); + if (thd->user_connect && thd->user_connect->user_resources.connections && + check_for_max_user_connections(thd, thd->user_connect)) + DBUG_RETURN(1); - /* Change database if necessary: OK or FAIL is sent in mysql_change_db */ - if (db && db[0]) - { - if (mysql_change_db(thd, db)) + /* Change database if necessary: OK or FAIL is sent in mysql_change_db */ + if (db && db[0]) { - if (thd->user_connect) - decrease_user_connections(thd->user_connect); - DBUG_RETURN(1); + if (mysql_change_db(thd, db)) + { + if (thd->user_connect) + decrease_user_connections(thd->user_connect); + DBUG_RETURN(-1); + } } + else + send_ok(thd); + thd->password= test(passwd_len); // remember for error messages + /* Ready to handle queries */ + DBUG_RETURN(0); } - else - send_ok(thd); - thd->password= test(passwd_len); // remember for error messages - /* Ready to handle queries */ } - else if (res != -1) // authentication failure + else if (res == 2) // client gave short hash, server has long hash { - net_printf(thd, ER_ACCESS_DENIED_ERROR, - thd->user, - thd->host_or_ip, - passwd_len ? ER(ER_YES) : ER(ER_NO)); - mysql_log.write(thd, COM_CONNECT, ER(ER_ACCESS_DENIED_ERROR), - thd->user, - thd->host_or_ip, - passwd_len ? ER(ER_YES) : ER(ER_NO)); + net_printf(thd, ER_NOT_SUPPORTED_AUTH_MODE); + mysql_log.write(thd,COM_CONNECT,ER(ER_NOT_SUPPORTED_AUTH_MODE)); + DBUG_RETURN(-1); } - DBUG_RETURN(res); + net_printf(thd, ER_ACCESS_DENIED_ERROR, + thd->user, + thd->host_or_ip, + passwd_len ? ER(ER_YES) : ER(ER_NO)); + mysql_log.write(thd, COM_CONNECT, ER(ER_ACCESS_DENIED_ERROR), + thd->user, + thd->host_or_ip, + passwd_len ? ER(ER_YES) : ER(ER_NO)); + DBUG_RETURN(-1); } /* @@ -492,60 +531,6 @@ static void reset_mqh(THD *thd, LEX_USER *lu, bool get_them= 0) /* - Perform check for scrambled password, re-request scrambled password - from client if necessary. See also help for check_user. - SYNOPSIS - authenticate() - RETURN VALUE - 0 success, OK sent to client - -1 error, sent to client - > 0 error, not sent to client -*/ - -static -int -authenticate(THD *thd, enum enum_server_command command, - const char *passwd, uint passwd_len, const char *db, - bool check_count) -{ - if (passwd_len != 0 && - passwd_len != SCRAMBLE_LENGTH && - passwd_len != SCRAMBLE_LENGTH_323) - return 1; - int res= check_user(thd, COM_CONNECT, passwd, passwd_len, db, check_count); - if (res < 0) - { - /* - This happens when client (new) sends password scrambled with - scramble(), but database holds old value (scrambled with - scramble_323()). Here we please client to send scrambled_password - in old format. - */ - char buff[NAME_LEN + 1]; - /* save db because network buffer is to hold new packet */ - if (db) - { - strmake(buff, db, NAME_LEN); - db= buff; - } - NET *net= &thd->net; - if (my_net_write(net, thd->scramble_323, SCRAMBLE_LENGTH_323 + 1) || - net_flush(net) || - my_net_read(net) != SCRAMBLE_LENGTH_323 + 1) // We have to read very - { // specific packet size - inc_host_errors(&thd->remote.sin_addr); - return ER_HANDSHAKE_ERROR; - } - /* Final attempt to check the user based on reply */ - /* So as passwd is short, errcode is always sent to user and res >= 0 */ - res= check_user(thd, COM_CONNECT, (char *) net->read_pos, - SCRAMBLE_LENGTH_323, db, check_count); - } - return res > 0 ? -1 : 0; -} - - -/* Perform handshake, authorize client and update thd ACL variables. SYNOPSIS check_connection() @@ -643,7 +628,7 @@ check_connection(THD *thd) /* Old clients does not understand long scrambles, but can ignore packet - tail: that's why first part of scramble is placed here, and second + tail: that's why first part of the scramble is placed here, and second part at the end of packet. */ end= strmake(end, thd->scramble_323, SCRAMBLE_LENGTH_323) + 1; @@ -760,17 +745,23 @@ check_connection(THD *thd) char *user= end; char *passwd= strend(user)+1; - uint passwd_len= strlen(passwd); - - char *db= thd->client_capabilities & CLIENT_CONNECT_WITH_DB ? - passwd+passwd_len+1 : 0; + char *db= passwd; + /* + Old clients send null-terminated string as password; new clients send + the size (1 byte) + string (not null-terminated). Hence in case of empty + password both send '\0'. + */ + uint passwd_len= thd->client_capabilities & CLIENT_SECURE_CONNECTION ? + *passwd++ : strlen(passwd); + db= thd->client_capabilities & CLIENT_CONNECT_WITH_DB ? + db + passwd_len + 1 : 0; if (thd->user) x_free(thd->user); thd->user= my_strdup(user, MYF(0)); if (!thd->user) return(ER_OUT_OF_RESOURCES); - return authenticate(thd, COM_CONNECT, passwd, passwd_len, db, true); + return check_user(thd, COM_CONNECT, passwd, passwd_len, db, true); } @@ -1137,8 +1128,15 @@ bool dispatch_command(enum enum_server_command command, THD *thd, statistic_increment(com_other, &LOCK_status); char *user= (char*) packet; char *passwd= strend(user)+1; - uint passwd_len= strlen(passwd); - char *db= passwd + passwd_len + 1; + /* + Old clients send null-terminated string ('\0' for empty string) for + password. New clients send the size (1 byte) + string (not null + terminated, so also '\0' for empty string). + */ + char *db= passwd; + uint passwd_len= thd->client_capabilities & CLIENT_SECURE_CONNECTION ? + *passwd++ : strlen(passwd); + db+= passwd_len + 1; /* Small check for incomming packet */ if ((uint) ((uchar*) db - net->read_pos) > packet_length) @@ -1163,7 +1161,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, break; } - int res= authenticate(thd, COM_CHANGE_USER, passwd, passwd_len, db, false); + int res= check_user(thd, COM_CHANGE_USER, passwd, passwd_len, db, false); if (res) { diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index c8c9eb97a6a..ddf4b71e891 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -493,6 +493,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %token MULTIPOINT %token MULTIPOLYGON %token NOW_SYM +%token OLD_PASSWORD %token PASSWORD %token POINTFROMTEXT %token POINT_SYM @@ -2516,9 +2517,11 @@ simple_expr: { $$= new Item_func_now($3); Lex->safe_to_cache_query=0;} | PASSWORD '(' expr ')' { - $$= use_old_passwords ? (Item *) new Item_func_old_password($3) : - (Item *) new Item_func_password($3); - } + $$= use_old_passwords ? (Item *) new Item_func_old_password($3) : + (Item *) new Item_func_password($3); + } + | OLD_PASSWORD '(' expr ')' + { $$= new Item_func_old_password($3); } | POINT_SYM '(' expr ',' expr ')' { $$= new Item_func_point($3,$5); } | POINTFROMTEXT '(' expr ')' @@ -4412,6 +4415,7 @@ keyword: | NO_SYM {} | NONE_SYM {} | OFFSET_SYM {} + | OLD_PASSWORD {} | OPEN_SYM {} | PACK_KEYS_SYM {} | PARTIAL {} @@ -4603,24 +4607,15 @@ text_or_password: TEXT_STRING { $$=$1.str;} | PASSWORD '(' TEXT_STRING ')' { - if (!$3.length) - $$=$3.str; - else if (use_old_passwords) - { - char *buff= (char *) - YYTHD->alloc(SCRAMBLED_PASSWORD_CHAR_LENGTH_323+1); - if (buff) - make_scrambled_password_323(buff, $3.str); - $$=buff; - } - else - { - char *buff= (char *) - YYTHD->alloc(SCRAMBLED_PASSWORD_CHAR_LENGTH+1); - if (buff) - make_scrambled_password(buff, $3.str); - $$=buff; - } + $$= $3.length ? use_old_passwords ? + Item_func_old_password::alloc(YYTHD, $3.str) : + Item_func_password::alloc(YYTHD, $3.str) : + $3.str; + } + | OLD_PASSWORD '(' TEXT_STRING ')' + { + $$= $3.length ? Item_func_old_password::alloc(YYTHD, $3.str) : + $3.str; } ; |