diff options
author | unknown <peter@mysql.com> | 2002-11-24 17:07:53 +0300 |
---|---|---|
committer | unknown <peter@mysql.com> | 2002-11-24 17:07:53 +0300 |
commit | 8c8b97fdf4756a699346ae1688136624d76713bc (patch) | |
tree | db7cb82e2166048d043214a331a5ad63bc7d0621 /libmysql | |
parent | 85bbdcf016dadf31335ad9ee98c3c8acfc167e2f (diff) | |
download | mariadb-git-8c8b97fdf4756a699346ae1688136624d76713bc.tar.gz |
SCRUM: Main change for Secure connection handling. Still needs some more coding. Commit
done for merge with newer version of code.
client/mysqladmin.c:
Support for new password format
include/mysql.h:
Increase buffer as new scramble is larger
include/mysql_com.h:
Add new prototypes for new auth handling
libmysql/libmysql.c:
New handshake handling code
mysql-test/install_test_db.sh:
Extend password length to handle new passwords
mysql-test/t/rpl000017-slave.sh:
Adjust test to work with longer password
scripts/mysql_fix_privilege_tables.sh:
Increase password length at priv table convertion
scripts/mysql_install_db.sh:
Longer passwords
sql/item_strfunc.cc:
New password generation function needs seed for password generation
sql/mini_client.cc:
Change MiniClient to handle new auth in replication
sql/mysqld.cc:
Remove unneeded flag (was added earlier for same change)
sql/password.c:
A lot of changes to handle new authentication and doccumentation
sql/sql_acl.cc:
Password handling function adjustment
sql/sql_acl.h:
Change prototype
sql/sql_class.h:
Extend scramble length
sql/sql_parse.cc:
Handling server side of new authentication
sql/sql_yacc.yy:
Adjustment for new prototypes
Diffstat (limited to 'libmysql')
-rw-r--r-- | libmysql/libmysql.c | 92 |
1 files changed, 83 insertions, 9 deletions
diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index f164582889e..db23caac5c7 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -67,7 +67,7 @@ ulong net_write_timeout= NET_WRITE_TIMEOUT; #define CLIENT_CAPABILITIES (CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG \ | CLIENT_LOCAL_FILES | CLIENT_TRANSACTIONS \ - | CLIENT_PROTOCOL_41) + | CLIENT_PROTOCOL_41 | CLIENT_SECURE_CONNECTION) #ifdef __WIN__ @@ -1585,6 +1585,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, { char buff[NAME_LEN+USERNAME_LENGTH+100],charset_name_buff[16]; char *end,*host_info,*charset_name; + char password_hash[20]; /* Used for tmp storage of stage1 hash */ my_socket sock; uint32 ip_addr; struct sockaddr_in sock_addr; @@ -1789,7 +1790,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, if ((pkt_length=net_safe_read(mysql)) == packet_error) goto error; - /* Check if version of protocoll matches current one */ + /* Check if version of protocol matches current one */ mysql->protocol_version= net->read_pos[0]; DBUG_DUMP("packet",(char*) net->read_pos,10); @@ -1855,7 +1856,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, } goto error; } - + /* Save connection information */ if (!user) user=""; if (!passwd) passwd=""; @@ -1962,32 +1963,105 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, DBUG_PRINT("info",("Server version = '%s' capabilites: %ld status: %d client_flag: %d", mysql->server_version,mysql->server_capabilities, mysql->server_status, client_flag)); - int3store(buff+2,max_allowed_packet); if (user && user[0]) strmake(buff+5,user,32); /* Max user name */ else read_user_name((char*) buff+5); + /* We have to handle different version of handshake here */ #ifdef _CUSTOMCONFIG_ #include "_cust_libmysql.h"; #endif DBUG_PRINT("info",("user: %s",buff+5)); - end=scramble(strend(buff+5)+1, mysql->scramble_buff, passwd, - (my_bool) (mysql->protocol_version == 9)); + /* + 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) + { + if (passwd[0]) + { + /* Use something for not empty password not to match it against empty one */ + end=scramble(strend(buff+5)+1, mysql->scramble_buff,"~MySQL#!", + (my_bool) (mysql->protocol_version == 9)); + } + else /* For empty password*/ + { + end=strend(buff+5)+1; + *end=0; /* Store zero length scramble */ + } + } + /* Real scramble is sent only for servers. This is to be blocked by option */ + else + end=scramble(strend(buff+5)+1, mysql->scramble_buff, passwd, + (my_bool) (mysql->protocol_version == 9)); + + /* Add database if needed */ if (db && (mysql->server_capabilities & CLIENT_CONNECT_WITH_DB)) { - end=strmake(end+1,db,NAME_LEN); + end=strmake(end+1,db,NAME_LEN); 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)) { - net->last_errno= CR_SERVER_LOST; + net->last_errno= CR_SERVER_LOST; strmov(net->last_error,ER(net->last_errno)); goto error; } - if (net_safe_read(mysql) == packet_error) + + /* We shall only query sever 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 basically always happen with new server unless empty password */ + if (pkt_length==24) /* We have new hash back */ + { + /* Old passwords will have zero 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,20); + /* Finally hash complete password using hash we got from server */ + password_hash_stage2(password_hash,net->read_pos); + /* Decypt and store scramble 4 = hash for stage2 */ + password_crypt(net->read_pos+4,mysql->scramble_buff,password_hash,20); + mysql->scramble_buff[20]=0; + /* Encode scramble with password. Recycle buffer */ + password_crypt(mysql->scramble_buff,buff,buff,20); + } + else + { + /* Create password to decode scramble */ + create_key_from_old_password(passwd,password_hash); + /* Decypt and store scramble 4 = hash for stage2 */ + password_crypt(net->read_pos+4,mysql->scramble_buff,password_hash,20); + mysql->scramble_buff[20]=0; + /* Finally scramble decoded scramble with password */ + scramble(buff, mysql->scramble_buff, passwd, + (my_bool) (mysql->protocol_version == 9)); + } + /* Write second package of authentication */ + if (my_net_write(net,buff,20) || net_flush(net)) + { + net->last_errno= CR_SERVER_LOST; + 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; + } + } + + /* End of authentication part of handshake */ + if (client_flag & CLIENT_COMPRESS) /* We will use compression */ net->compress=1; if (db && mysql_select_db(mysql,db)) |