summaryrefslogtreecommitdiff
path: root/sql-common
diff options
context:
space:
mode:
authorunknown <kostja@oak.local>2003-09-03 14:12:10 +0400
committerunknown <kostja@oak.local>2003-09-03 14:12:10 +0400
commit49b0312dd7afe5a60a9d6aa22daff79bf50f0a84 (patch)
tree4aa3e74d29fde5abc55c20c2c14e6c286e467c6e /sql-common
parent651898adfce345138363961769c6fdfd6da95532 (diff)
parent0188e158c1d29057cb8a449891894c69dd2f5f2b (diff)
downloadmariadb-git-49b0312dd7afe5a60a9d6aa22daff79bf50f0a84.tar.gz
merge commit, hope that none of bar and dlenev changes were
lost. BitKeeper/etc/logging_ok: auto-union include/mysql.h: Auto merged include/mysql_com.h: Auto merged libmysql/libmysql.c: Auto merged scripts/mysql_fix_privilege_tables.sql: Auto merged sql/item_create.cc: Auto merged sql/item_create.h: Auto merged sql/item_strfunc.cc: Auto merged sql/item_strfunc.h: Auto merged sql/lex.h: Auto merged sql/mysqld.cc: Auto merged sql/protocol.h: Auto merged sql/set_var.cc: Auto merged sql/sql_acl.h: Auto merged sql/sql_class.cc: Auto merged sql/sql_class.h: Auto merged sql/sql_yacc.yy: Auto merged include/mysqld_error.h: merge commit: new error message added sql-common/client.c: merge commit sql/mysql_priv.h: merge commit: autoremerge sql/set_var.h: merge commit sql/share/czech/errmsg.txt: merge commit sql/share/danish/errmsg.txt: merge commit sql/share/dutch/errmsg.txt: merge commit sql/share/english/errmsg.txt: merge commit sql/share/estonian/errmsg.txt: merge commit sql/share/french/errmsg.txt: merge commit sql/share/german/errmsg.txt: merge commit sql/share/greek/errmsg.txt: merge commit sql/share/hungarian/errmsg.txt: merge commit sql/share/italian/errmsg.txt: merge commit sql/share/japanese/errmsg.txt: merge commit sql/share/korean/errmsg.txt: merge commit sql/share/norwegian-ny/errmsg.txt: merge commit sql/share/norwegian/errmsg.txt: merge commit sql/share/polish/errmsg.txt: merge commit sql/share/portuguese/errmsg.txt: merge commit sql/share/romanian/errmsg.txt: merge commit sql/share/russian/errmsg.txt: merge commit sql/share/serbian/errmsg.txt: merge commit sql/share/slovak/errmsg.txt: merge commit sql/share/spanish/errmsg.txt: merge commit sql/share/swedish/errmsg.txt: merge commit sql/share/ukrainian/errmsg.txt: merge commit sql/slave.cc: merge commit sql/slave.h: merge commit sql/sql_acl.cc: merge commit sql/sql_parse.cc: merge commit sql/sql_repl.h: merge commit
Diffstat (limited to 'sql-common')
-rw-r--r--sql-common/client.c170
1 files changed, 68 insertions, 102 deletions
diff --git a/sql-common/client.c b/sql-common/client.c
index e410330d616..b4d875b8132 100644
--- a/sql-common/client.c
+++ b/sql-common/client.c
@@ -1392,76 +1392,6 @@ mysql_ssl_free(MYSQL *mysql __attribute__((unused)))
/*
- Handle password authentication
-*/
-
-my_bool mysql_autenticate(MYSQL *mysql, const char *passwd)
-{
- ulong pkt_length;
- NET *net= &mysql->net;
- char buff[SCRAMBLE41_LENGTH];
- char password_hash[SCRAMBLE41_LENGTH]; /* Used for storage of stage1 hash */
-
- /* We shall only query server if it expect us to do so */
- if ((pkt_length=net_safe_read(mysql)) == packet_error)
- goto error;
-
- if (mysql->server_capabilities & CLIENT_SECURE_CONNECTION)
- {
- /*
- This should always happen with new server unless empty password
- OK/Error packets have zero as the first char
- */
- if (pkt_length == 24 && net->read_pos[0])
- {
- /* Old passwords will have '*' at the first byte of hash */
- if (net->read_pos[0] != '*')
- {
- /* Build full password hash as it is required to decode scramble */
- password_hash_stage1(buff, passwd);
- /* Store copy as we'll need it later */
- memcpy(password_hash,buff,SCRAMBLE41_LENGTH);
- /* Finally hash complete password using hash we got from server */
- password_hash_stage2(password_hash,(const char*) net->read_pos);
- /* Decypt and store scramble 4 = hash for stage2 */
- password_crypt((const char*) net->read_pos+4,mysql->scramble_buff,
- password_hash, SCRAMBLE41_LENGTH);
- mysql->scramble_buff[SCRAMBLE41_LENGTH]=0;
- /* Encode scramble with password. Recycle buffer */
- password_crypt(mysql->scramble_buff,buff,buff,SCRAMBLE41_LENGTH);
- }
- else
- {
- /* Create password to decode scramble */
- create_key_from_old_password(passwd,password_hash);
- /* Decypt and store scramble 4 = hash for stage2 */
- password_crypt((const char*) net->read_pos+4,mysql->scramble_buff,
- password_hash, SCRAMBLE41_LENGTH);
- mysql->scramble_buff[SCRAMBLE41_LENGTH]=0;
- /* Finally scramble decoded scramble with password */
- scramble(buff, mysql->scramble_buff, passwd,0);
- }
- /* Write second package of authentication */
- if (my_net_write(net,buff,SCRAMBLE41_LENGTH) || net_flush(net))
- {
- net->last_errno= CR_SERVER_LOST;
- strmov(net->sqlstate, unknown_sqlstate);
- strmov(net->last_error,ER(net->last_errno));
- goto error;
- }
- /* Read what server thinks about out new auth message report */
- if (net_safe_read(mysql) == packet_error)
- goto error;
- }
- }
- return 0;
-
-error:
- return 1;
-}
-
-
-/*
Note that the mysql argument must be initialized with mysql_init()
before calling mysql_real_connect !
*/
@@ -1553,7 +1483,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
mysql->server_status=SERVER_STATUS_AUTOCOMMIT;
/*
- Grab a socket and connect it to the server
+ Part 0: Grab a socket and connect it to the server
*/
#if defined(HAVE_SMEM)
if ((!mysql->options.protocol ||
@@ -1754,6 +1684,11 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
strmov(net->last_error,ER(net->last_errno));
goto error;
}
+
+ /*
+ Part 1: Connection established, read and parse first packet
+ */
+
if ((pkt_length=net_safe_read(mysql)) == packet_error)
goto error;
@@ -1774,8 +1709,13 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
end=strend((char*) net->read_pos+1);
mysql->thread_id=uint4korr(end+1);
end+=5;
- strmake(mysql->scramble_buff,end,8);
- end+=9;
+ /*
+ Scramble is split into two parts because old clients does not understand
+ long scrambles; here goes the first part.
+ */
+ strmake(mysql->scramble, end, SCRAMBLE_LENGTH_323);
+ end+= SCRAMBLE_LENGTH_323+1;
+
if (pkt_length >= (uint) (end+1 - (char*) net->read_pos))
mysql->server_capabilities=uint2korr(end);
if (pkt_length >= (uint) (end+18 - (char*) net->read_pos))
@@ -1784,6 +1724,14 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
mysql->server_language=end[2];
mysql->server_status=uint2korr(end+3);
}
+ end+= 18;
+ if (pkt_length >= (uint) (end + SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323 + 1 -
+ (char *) net->read_pos))
+ strmake(mysql->scramble+SCRAMBLE_LENGTH_323, end,
+ SCRAMBLE_LENGTH-SCRAMBLE_LENGTH_323);
+ else
+ mysql->server_capabilities&= ~CLIENT_SECURE_CONNECTION;
+
charset_number= mysql->server_language;
/* Set character set */
@@ -1860,9 +1808,12 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
mysql->unix_socket=0;
strmov(mysql->server_version,(char*) net->read_pos+1);
mysql->port=port;
- client_flag|=mysql->options.client_flag;
- /* Send client information for access check */
+ /*
+ Part 2: format and send client info to the server for access check
+ */
+
+ client_flag|=mysql->options.client_flag;
client_flag|=CLIENT_CAPABILITIES;
if (client_flag & CLIENT_MULTI_QUERIES)
client_flag|= CLIENT_MULTI_RESULTS;
@@ -1949,7 +1900,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
mysql->server_status, client_flag));
/* This needs to be changed as it's not useful with big packets */
if (user && user[0])
- strmake(end,user,32); /* Max user name */
+ strmake(end,user,USERNAME_LENGTH); /* Max user name */
else
read_user_name((char*) end);
@@ -1958,41 +1909,30 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
#include "_cust_libmysql.h"
#endif
DBUG_PRINT("info",("user: %s",end));
- /*
- We always start with old type handshake the only difference is message sent
- If server handles secure connection type we'll not send the real scramble
- */
- if (mysql->server_capabilities & CLIENT_SECURE_CONNECTION)
+ end= strend(end) + 1;
+ if (passwd[0])
{
- if (passwd[0])
+ if (mysql->server_capabilities & CLIENT_SECURE_CONNECTION)
{
- /* Prepare false scramble */
- end=strend(end)+1;
- bfill(end, SCRAMBLE_LENGTH, 'x');
- end+=SCRAMBLE_LENGTH;
- *end=0;
+ *end++= SCRAMBLE_LENGTH;
+ scramble(end, mysql->scramble, passwd);
+ end+= SCRAMBLE_LENGTH;
}
- else /* For empty password*/
+ else
{
- end=strend(end)+1;
- *end=0; /* Store zero length scramble */
+ scramble_323(end, mysql->scramble, passwd);
+ end+= SCRAMBLE_LENGTH_323 + 1;
}
}
else
- {
- /*
- Real scramble is only sent to old servers. This can be blocked
- by calling mysql_options(MYSQL *, MYSQL_SECURE_CONNECT, (char*) &1);
- */
- end=scramble(strend(end)+1, mysql->scramble_buff, passwd,
- (my_bool) (mysql->protocol_version == 9));
- }
+ *end++= '\0'; /* empty password */
+
/* Add database if needed */
if (db && (mysql->server_capabilities & CLIENT_CONNECT_WITH_DB))
{
- end=strmake(end+1,db,NAME_LEN);
- mysql->db=my_strdup(db,MYF(MY_WME));
- db=0;
+ end= strmake(end, db, NAME_LEN) + 1;
+ mysql->db= my_strdup(db,MYF(MY_WME));
+ db= 0;
}
/* Write authentication package */
if (my_net_write(net,buff,(ulong) (end-buff)) || net_flush(net))
@@ -2002,10 +1942,36 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
strmov(net->last_error,ER(net->last_errno));
goto error;
}
+
+ /*
+ Part 3: Authorization data's been sent. Now server can reply with
+ OK-packet, or re-request scrambled password.
+ */
- if (mysql_autenticate(mysql, passwd))
+ if ((pkt_length=net_safe_read(mysql)) == packet_error)
goto error;
+ if (pkt_length == 1 && net->read_pos[0] == 254 &&
+ mysql->server_capabilities & CLIENT_SECURE_CONNECTION)
+ {
+ /*
+ By sending this very specific reply server asks us to send scrambled
+ password in old format.
+ */
+ scramble_323(buff, mysql->scramble, passwd);
+ if (my_net_write(net, buff, SCRAMBLE_LENGTH_323 + 1) || net_flush(net))
+ {
+ net->last_errno= CR_SERVER_LOST;
+ strmov(net->sqlstate, unknown_sqlstate);
+ strmov(net->last_error,ER(net->last_errno));
+ goto error;
+ }
+ /* Read what server thinks about out new auth message report */
+ if (net_safe_read(mysql) == packet_error)
+ goto error;
+ }
+
+
if (client_flag & CLIENT_COMPRESS) /* We will use compression */
net->compress=1;