Commit bec1d903 authored by Sergei Golubchik's avatar Sergei Golubchik

Do the partial merge of WL#5602 correctly:

  Remove unused code (that should not have been merged)
  Add protocol extension (that should have been merged)
  Fix bugs (see pack.c)
parent 6ae5f0ef
/* defines and prototypes for using crypt_genhash_impl.cc */
#ifndef CRYPT_HASHGEN_IMPL_H
#define CRYPT_HASHGEN_IMPL_H
#define ROUNDS_DEFAULT 5000
#define ROUNDS_MIN 1000
#define ROUNDS_MAX 999999999
#define MIXCHARS 32
#define CRYPT_SALT_LENGTH 20
#define CRYPT_MAGIC_LENGTH 3
#define CRYPT_PARAM_LENGTH 13
#define SHA256_HASH_LENGTH 43
#define CRYPT_MAX_PASSWORD_SIZE (CRYPT_SALT_LENGTH + \
SHA256_HASH_LENGTH + \
CRYPT_MAGIC_LENGTH + \
CRYPT_PARAM_LENGTH)
int extract_user_salt(char **salt_begin,
char **salt_end);
C_MODE_START
char *
my_crypt_genhash(char *ctbuffer,
size_t ctbufflen,
const char *plaintext,
int plaintext_len,
const char *switchsalt,
const char **params);
void generate_user_salt(char *buffer, int buffer_len);
void xor_string(char *to, int to_len, char *pattern, int pattern_len);
C_MODE_END
#endif
#ifndef CLIENT_AUTHENTICATION_H
#define CLIENT_AUTHENTICATION_H
#include "mysql.h"
#include "mysql/client_plugin.h"
C_MODE_START
int sha256_password_auth_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql);
int sha256_password_init(char *, size_t, int, va_list);
int sha256_password_deinit(void);
C_MODE_END
#endif
...@@ -265,11 +265,11 @@ enum enum_server_command ...@@ -265,11 +265,11 @@ enum enum_server_command
CLIENT_REMEMBER_OPTIONS | \ CLIENT_REMEMBER_OPTIONS | \
CLIENT_PROGRESS | \ CLIENT_PROGRESS | \
CLIENT_PLUGIN_AUTH | \ CLIENT_PLUGIN_AUTH | \
CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA | \
CLIENT_CONNECT_ATTRS) CLIENT_CONNECT_ATTRS)
/* /*
To be added later: To be added later:
CLIENT_CONNECT_ATTRS, CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA,
CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS
*/ */
...@@ -641,7 +641,9 @@ void my_thread_end(void); ...@@ -641,7 +641,9 @@ void my_thread_end(void);
#ifdef MY_GLOBAL_INCLUDED #ifdef MY_GLOBAL_INCLUDED
ulong STDCALL net_field_length(uchar **packet); ulong STDCALL net_field_length(uchar **packet);
my_ulonglong net_field_length_ll(uchar **packet); my_ulonglong net_field_length_ll(uchar **packet);
my_ulonglong safe_net_field_length_ll(uchar **packet, size_t packet_len);
uchar *net_store_length(uchar *pkg, ulonglong length); uchar *net_store_length(uchar *pkg, ulonglong length);
uchar *safe_net_store_length(uchar *pkg, size_t pkg_len, ulonglong length);
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus
......
...@@ -24,8 +24,6 @@ void my_make_scrambled_password_323(char *to, const char *password, ...@@ -24,8 +24,6 @@ void my_make_scrambled_password_323(char *to, const char *password,
size_t pass_len); size_t pass_len);
void my_make_scrambled_password(char *to, const char *password, void my_make_scrambled_password(char *to, const char *password,
size_t pass_len); size_t pass_len);
void my_make_scrambled_password_sha1(char *to, const char *password,
size_t pass_len);
void hash_password(ulong *result, const char *password, uint password_len); void hash_password(ulong *result, const char *password, uint password_len);
......
...@@ -35,7 +35,6 @@ struct st_mysql_options_extention { ...@@ -35,7 +35,6 @@ struct st_mysql_options_extention {
char *default_auth; char *default_auth;
char *ssl_crl; /* PEM CRL file */ char *ssl_crl; /* PEM CRL file */
char *ssl_crlpath; /* PEM directory of CRL-s? */ char *ssl_crlpath; /* PEM directory of CRL-s? */
char *server_public_key_path;
void (*report_progress)(const MYSQL *mysql, void (*report_progress)(const MYSQL *mysql,
unsigned int stage, unsigned int stage,
unsigned int max_stage, unsigned int max_stage,
......
...@@ -337,7 +337,6 @@ SET(CLIENT_SOURCES ...@@ -337,7 +337,6 @@ SET(CLIENT_SOURCES
../sql-common/mysql_async.c ../sql-common/mysql_async.c
../sql-common/my_time.c ../sql-common/my_time.c
../sql-common/client_plugin.c ../sql-common/client_plugin.c
../sql-common/client_authentication.cc
../sql/net_serv.cc ../sql/net_serv.cc
../sql-common/pack.c ../sql-common/pack.c
../sql/password.c ../sql/password.c
......
...@@ -35,6 +35,7 @@ extern char * mysql_unix_port; ...@@ -35,6 +35,7 @@ extern char * mysql_unix_port;
CLIENT_MULTI_RESULTS | \ CLIENT_MULTI_RESULTS | \
CLIENT_PS_MULTI_RESULTS | \ CLIENT_PS_MULTI_RESULTS | \
CLIENT_PLUGIN_AUTH | \ CLIENT_PLUGIN_AUTH | \
CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA | \
CLIENT_CONNECT_ATTRS) CLIENT_CONNECT_ATTRS)
sig_handler my_pipe_sig_handler(int sig); sig_handler my_pipe_sig_handler(int sig);
......
...@@ -26,7 +26,6 @@ ENDIF() ...@@ -26,7 +26,6 @@ ENDIF()
# must be compiled with "-fvisibility=hidden" # must be compiled with "-fvisibility=hidden"
IF(WITH_SSL STREQUAL "bundled" AND HAVE_VISIBILITY_HIDDEN) IF(WITH_SSL STREQUAL "bundled" AND HAVE_VISIBILITY_HIDDEN)
SET_SOURCE_FILES_PROPERTIES( SET_SOURCE_FILES_PROPERTIES(
crypt_genhash_impl.cc
my_aes.cc my_aes.cc
my_md5.cc my_md5.cc
my_sha1.cc my_sha1.cc
...@@ -35,7 +34,6 @@ IF(WITH_SSL STREQUAL "bundled" AND HAVE_VISIBILITY_HIDDEN) ...@@ -35,7 +34,6 @@ IF(WITH_SSL STREQUAL "bundled" AND HAVE_VISIBILITY_HIDDEN)
ENDIF() ENDIF()
SET(MYSYS_SSL_SOURCES SET(MYSYS_SSL_SOURCES
crypt_genhash_impl.cc
my_aes.cc my_aes.cc
my_sha1.cc my_sha1.cc
my_sha2.cc my_sha2.cc
......
This diff is collapsed.
...@@ -2477,6 +2477,29 @@ typedef struct { ...@@ -2477,6 +2477,29 @@ typedef struct {
int last_read_packet_len; /**< the length of the last *read* packet */ int last_read_packet_len; /**< the length of the last *read* packet */
} MCPVIO_EXT; } MCPVIO_EXT;
/*
Write 1-8 bytes of string length header infromation to dest depending on
value of src_len, then copy src_len bytes from src to dest.
@param dest Destination buffer of size src_len+8
@param dest_end One byte past the end of the dest buffer
@param src Source buff of size src_len
@param src_end One byte past the end of the src buffer
@return pointer dest+src_len+header size or NULL if
*/
static uchar *write_length_encoded_string4(uchar *dst, size_t dst_len,
const uchar *src, size_t src_len)
{
uchar *to= safe_net_store_length(dst, dst_len, src_len);
if (to == NULL)
return NULL;
memcpy(to, src, src_len);
return to + src_len;
}
/** /**
sends a COM_CHANGE_USER command with a caller provided payload sends a COM_CHANGE_USER command with a caller provided payload
...@@ -2578,7 +2601,7 @@ static int send_change_user_packet(MCPVIO_EXT *mpvio, ...@@ -2578,7 +2601,7 @@ static int send_change_user_packet(MCPVIO_EXT *mpvio,
1 charset number 1 charset number
23 reserved (always 0) 23 reserved (always 0)
n user name, \0-terminated n user name, \0-terminated
n plugin auth data (e.g. scramble), length (1 byte) coded n plugin auth data (e.g. scramble), length encoded
n database name, \0-terminated n database name, \0-terminated
(if CLIENT_CONNECT_WITH_DB is set in the capabilities) (if CLIENT_CONNECT_WITH_DB is set in the capabilities)
n client auth plugin name - \0-terminated string, n client auth plugin name - \0-terminated string,
...@@ -2736,10 +2759,20 @@ static int send_client_reply_packet(MCPVIO_EXT *mpvio, ...@@ -2736,10 +2759,20 @@ static int send_client_reply_packet(MCPVIO_EXT *mpvio,
{ {
if (mysql->server_capabilities & CLIENT_SECURE_CONNECTION) if (mysql->server_capabilities & CLIENT_SECURE_CONNECTION)
{ {
if (mysql->server_capabilities & CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA)
end= (char*)write_length_encoded_string4((uchar*)end,
buff_size, data, data_len);
else
{
if (data_len > 255)
goto error;
*end++= data_len; *end++= data_len;
memcpy(end, data, data_len); memcpy(end, data, data_len);
end+= data_len; end+= data_len;
} }
if (end == NULL)
goto error;
}
else else
{ {
DBUG_ASSERT(data_len == SCRAMBLE_LENGTH_323 + 1); /* incl. \0 at the end */ DBUG_ASSERT(data_len == SCRAMBLE_LENGTH_323 + 1); /* incl. \0 at the end */
......
/* Copyright (c) 2012, Oracle and/or its affiliates.
Copyright (c) 2013, Monty Program Ab
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02111-1307 USA */
#include <my_global.h>
#if defined(HAVE_OPENSSL)
#include "crypt_genhash_impl.h"
#include "mysql/client_authentication.h"
#include "m_ctype.h"
#include "sql_common.h"
#include "errmsg.h"
#include "m_string.h"
#include <string.h>
#if !defined(HAVE_YASSL)
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/err.h>
#if defined(_WIN32) && !defined(_OPENSSL_Applink) && defined(HAVE_OPENSSL_APPLINK_C)
#include <openssl/applink.c>
#endif
#endif
#include "mysql/service_my_plugin_log.h"
#define MAX_CIPHER_LENGTH 1024
#if !defined(HAVE_YASSL)
mysql_mutex_t g_public_key_mutex;
#endif
int sha256_password_init(char *a, size_t b, int c, va_list d)
{
#if !defined(HAVE_YASSL)
mysql_mutex_init(0,&g_public_key_mutex, MY_MUTEX_INIT_SLOW);
#endif
return 0;
}
int sha256_password_deinit(void)
{
#if !defined(HAVE_YASSL)
mysql_mutex_destroy(&g_public_key_mutex);
#endif
return 0;
}
#if !defined(HAVE_YASSL)
/**
Reads and parse RSA public key data from a file.
@param mysql connection handle with file path data
@return Pointer to the RSA public key storage buffer
*/
RSA *rsa_init(MYSQL *mysql)
{
static RSA *g_public_key= NULL;
RSA *key= NULL;
mysql_mutex_lock(&g_public_key_mutex);
key= g_public_key;
mysql_mutex_unlock(&g_public_key_mutex);
if (key != NULL)
return key;
FILE *pub_key_file= NULL;
if (mysql->options.extension != NULL &&
mysql->options.extension->server_public_key_path != NULL &&
mysql->options.extension->server_public_key_path != '\0')
{
pub_key_file= fopen(mysql->options.extension->server_public_key_path,
"r");
}
/* No public key is used; return 0 without errors to indicate this. */
else
return 0;
if (pub_key_file == NULL)
{
/*
If a key path was submitted but no key located then we print an error
message. Else we just report that there is no public key.
*/
fprintf(stderr,"Can't locate server public key '%s'\n",
mysql->options.extension->server_public_key_path);
return 0;
}
mysql_mutex_lock(&g_public_key_mutex);
key= g_public_key= PEM_read_RSA_PUBKEY(pub_key_file, 0, 0, 0);
mysql_mutex_unlock(&g_public_key_mutex);
fclose(pub_key_file);
if (g_public_key == NULL)
{
fprintf(stderr, "Public key is not in PEM format: '%s'\n",
mysql->options.extension->server_public_key_path);
return 0;
}
return key;
}
#endif // !defined(HAVE_YASSL)
/**
Authenticate the client using the RSA or TLS and a SHA256 salted password.
@param vio Provides plugin access to communication channel
@param mysql Client connection handler
@return Error status
@retval CR_ERROR An error occurred.
@retval CR_OK Authentication succeeded.
*/
extern "C"
int sha256_password_auth_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql)
{
bool uses_password= mysql->passwd[0] != 0;
#if !defined(HAVE_YASSL)
unsigned char encrypted_password[MAX_CIPHER_LENGTH];
static char request_public_key= '\1';
RSA *public_key= NULL;
bool got_public_key_from_server= false;
#endif
bool connection_is_secure= false;
unsigned char scramble_pkt[20];
unsigned char *pkt;
DBUG_ENTER("sha256_password_auth_client");
/*
Get the scramble from the server because we need it when sending encrypted
password.
*/
if (vio->read_packet(vio, &pkt) != SCRAMBLE_LENGTH)
{
DBUG_PRINT("info",("Scramble is not of correct length."));
DBUG_RETURN(CR_ERROR);
}
/*
Copy the scramble to the stack or it will be lost on the next use of the
net buffer.
*/
memcpy(scramble_pkt, pkt, SCRAMBLE_LENGTH);
if (mysql_get_ssl_cipher(mysql) != NULL)
connection_is_secure= true;
/* If connection isn't secure attempt to get the RSA public key file */
if (!connection_is_secure)
{
#if !defined(HAVE_YASSL)
public_key= rsa_init(mysql);
#endif
}
if (!uses_password)
{
/* We're not using a password */
static const unsigned char zero_byte= '\0';
if (vio->write_packet(vio, (const unsigned char *) &zero_byte, 1))
DBUG_RETURN(CR_ERROR);
}
else
{
/* Password is a 0-terminated byte array ('\0' character included) */
unsigned int passwd_len= strlen(mysql->passwd) + 1;
if (!connection_is_secure)
{
#if !defined(HAVE_YASSL)
/*
If no public key; request one from the server.
*/
if (public_key == NULL)
{
if (vio->write_packet(vio, (const unsigned char *) &request_public_key,
1))
DBUG_RETURN(CR_ERROR);
int pkt_len= 0;
unsigned char *pkt;
if ((pkt_len= vio->read_packet(vio, &pkt)) == -1)
DBUG_RETURN(CR_ERROR);
BIO* bio= BIO_new_mem_buf(pkt, pkt_len);
public_key= PEM_read_bio_RSA_PUBKEY(bio, NULL, NULL, NULL);
BIO_free(bio);
if (public_key == 0)
DBUG_RETURN(CR_ERROR);
got_public_key_from_server= true;
}
/* Obfuscate the plain text password with the session scramble */
xor_string(mysql->passwd, strlen(mysql->passwd), (char *) scramble_pkt,
SCRAMBLE_LENGTH);
/* Encrypt the password and send it to the server */
int cipher_length= RSA_size(public_key);
/*
When using RSA_PKCS1_OAEP_PADDING the password length must be less
than RSA_size(rsa) - 41.
*/
if (passwd_len + 41 >= (unsigned) cipher_length)
{
/* password message is to long */
DBUG_RETURN(CR_ERROR);
}
RSA_public_encrypt(passwd_len, (unsigned char *) mysql->passwd,
encrypted_password,
public_key, RSA_PKCS1_OAEP_PADDING);
if (got_public_key_from_server)
RSA_free(public_key);
if (vio->write_packet(vio, (uchar*) encrypted_password, cipher_length))
DBUG_RETURN(CR_ERROR);
#else
set_mysql_extended_error(mysql, CR_AUTH_PLUGIN_ERR, unknown_sqlstate,
ER(CR_AUTH_PLUGIN_ERR), "sha256_password",
"Authentication requires SSL encryption");
DBUG_RETURN(CR_ERROR); // If no openssl support
#endif
}
else
{
/* The vio is encrypted already; just send the plain text passwd */
if (vio->write_packet(vio, (uchar*) mysql->passwd, passwd_len))
DBUG_RETURN(CR_ERROR);
}
memset(mysql->passwd, 0, passwd_len);
}
DBUG_RETURN(CR_OK);
}
#endif
...@@ -48,7 +48,7 @@ ulong STDCALL net_field_length(uchar **packet) ...@@ -48,7 +48,7 @@ ulong STDCALL net_field_length(uchar **packet)
/* The same as above but returns longlong */ /* The same as above but returns longlong */
my_ulonglong net_field_length_ll(uchar **packet) my_ulonglong net_field_length_ll(uchar **packet)
{ {
reg1 uchar *pos= *packet; uchar *pos= *packet;
if (*pos < 251) if (*pos < 251)
{ {
(*packet)++; (*packet)++;
...@@ -69,12 +69,47 @@ my_ulonglong net_field_length_ll(uchar **packet) ...@@ -69,12 +69,47 @@ my_ulonglong net_field_length_ll(uchar **packet)
(*packet)+=4; (*packet)+=4;
return (my_ulonglong) uint3korr(pos+1); return (my_ulonglong) uint3korr(pos+1);
} }
DBUG_ASSERT(*pos == 254);
(*packet)+=9; /* Must be 254 when here */ (*packet)+=9; /* Must be 254 when here */
#ifdef NO_CLIENT_LONGLONG
return (my_ulonglong) uint4korr(pos+1);
#else
return (my_ulonglong) uint8korr(pos+1); return (my_ulonglong) uint8korr(pos+1);
#endif }
my_ulonglong safe_net_field_length_ll(uchar **packet, size_t packet_len)
{
uchar *pos= *packet;
if (packet_len < 1)
goto err;
if (*pos < 251)
{
(*packet)++;
return (my_ulonglong) *pos;
}
if (*pos == 251)
{
(*packet)++;
return (my_ulonglong) NULL_LENGTH;
}
if (*pos == 252)
{
if (packet_len < 3)
goto err;
(*packet)+=3;
return (my_ulonglong) uint2korr(pos+1);
}
if (*pos == 253)
{
if (packet_len < 4)
goto err;
(*packet)+=4;
return (my_ulonglong) uint3korr(pos+1);
}
if (packet_len < 9 || *pos != 254)
goto err;
(*packet)+=9;
return (my_ulonglong) uint8korr(pos+1);
err:
*packet = NULL;
return 0;
} }
/* /*
...@@ -82,38 +117,69 @@ my_ulonglong net_field_length_ll(uchar **packet) ...@@ -82,38 +117,69 @@ my_ulonglong net_field_length_ll(uchar **packet)
SYNOPSIS SYNOPSIS
net_store_length() net_store_length()
pkg Store the packed integer here packet Store the packed integer here
length integers to store length integers to store
NOTES NOTES
This is mostly used to store lengths of strings. This is mostly used to store lengths of strings.
We have to cast the result for the LL() becasue of a bug in Forte CC
compiler.
RETURN RETURN
Position in 'pkg' after the packed length Position in 'packet' after the packed length
*/ */
uchar *net_store_length(uchar *packet, ulonglong length) uchar *net_store_length(uchar *packet, ulonglong length)
{ {
if (length < (ulonglong) 251LL) if (length < 251)
{
*packet= (uchar) length;
return packet+1;
}
/* 251 is reserved for NULL */
if (length < 65536)
{
*packet++=252;
int2store(packet, (uint) length);
return packet+2;
}
if (length < 16777216)
{
*packet++=253;
int3store(packet, (ulong) length);
return packet+3;
}
*packet++=254;
int8store(packet,length);
return packet+8;
}
uchar *safe_net_store_length(uchar *packet, size_t packet_len, ulonglong length)
{
if (length < 251)
{ {
*packet=(uchar) length; if (packet_len < 1)
return NULL;
*packet= (uchar) length;
return packet+1; return packet+1;
} }
/* 251 is reserved for NULL */ /* 251 is reserved for NULL */
if (length < (ulonglong) 65536LL) if (length < 65536)
{ {
if (packet_len < 3)
return NULL;
*packet++=252; *packet++=252;
int2store(packet,(uint) length); int2store(packet, (uint) length);
return packet+2; return packet+2;
} }
if (length < (ulonglong) 16777216LL) if (length < 16777216)
{ {
if (packet_len < 4)
return NULL;
*packet++=253; *packet++=253;
int3store(packet,(ulong) length); int3store(packet, (ulong) length);
return packet+3; return packet+3;
} }
if (packet_len < 9)
return NULL;
*packet++=254; *packet++=254;
int8store(packet,length); int8store(packet,length);
return packet+8; return packet+8;
......
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
CLIENT_PROTOCOL_41 | \ CLIENT_PROTOCOL_41 | \
CLIENT_SECURE_CONNECTION | \ CLIENT_SECURE_CONNECTION | \
CLIENT_PLUGIN_AUTH | \ CLIENT_PLUGIN_AUTH | \
CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA | \
CLIENT_CONNECT_ATTRS) CLIENT_CONNECT_ATTRS)
#define read_user_name(A) {} #define read_user_name(A) {}
......
...@@ -2171,129 +2171,28 @@ void Item_func_trim::print(String *str, enum_query_type query_type) ...@@ -2171,129 +2171,28 @@ void Item_func_trim::print(String *str, enum_query_type query_type)
/* Item_func_password */ /* Item_func_password */
/**
Helper function for calculating a new password. Used in
Item_func_password::fix_length_and_dec() for const parameters and in
Item_func_password::val_str_ascii() for non-const parameters.
@param str The plain text password which should be digested
@param buffer a pointer to the buffer where the digest will be stored.
@note The buffer must be of at least CRYPT_MAX_PASSWORD_SIZE size.
@return Size of the password.
*/
static int calculate_password(String *str, char *buffer)
{
DBUG_ASSERT(str);
if (str->length() == 0) // PASSWORD('') returns ''
return 0;
int buffer_len= 0;
THD *thd= current_thd;
int old_passwords= 0;
if (thd)
old_passwords= thd->variables.old_passwords;
#if defined(HAVE_OPENSSL)
if (old_passwords == 2)
{
my_make_scrambled_password(buffer, str->ptr(),
str->length());
buffer_len= (int) strlen(buffer) + 1;
}
else
#endif
if (old_passwords == 0)
{
my_make_scrambled_password_sha1(buffer, str->ptr(),
str->length());
buffer_len= SCRAMBLED_PASSWORD_CHAR_LENGTH;
}
else
if (old_passwords == 1)
{
my_make_scrambled_password_323(buffer, str->ptr(),
str->length());
buffer_len= SCRAMBLED_PASSWORD_CHAR_LENGTH_323;
}
return buffer_len;
}
/* Item_func_password */
void Item_func_password::fix_length_and_dec()
{
maybe_null= false; // PASSWORD() never returns NULL
if (args[0]->const_item())
{
String str;
String *res= args[0]->val_str(&str);
if (!args[0]->null_value)
{
m_hashed_password_buffer_len=
calculate_password(res, m_hashed_password_buffer);
fix_length_and_charset(m_hashed_password_buffer_len, default_charset());
m_recalculate_password= false;
return;
}
}
m_recalculate_password= true;
fix_length_and_charset(CRYPT_MAX_PASSWORD_SIZE, default_charset());
}
String *Item_func_password::val_str_ascii(String *str) String *Item_func_password::val_str_ascii(String *str)
{ {
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
String *res= args[0]->val_str(str); String *res= args[0]->val_str(str);
if (args[0]->null_value)
res= make_empty_result();
/* we treat NULLs as equal to empty string when calling the plugin */
check_password_policy(res); check_password_policy(res);
if (args[0]->null_value || res->length() == 0)
null_value= 0;
if (args[0]->null_value) // PASSWORD(NULL) returns ''
return res;
if (m_recalculate_password)
m_hashed_password_buffer_len= calculate_password(res,
m_hashed_password_buffer);
if (m_hashed_password_buffer_len == 0)
return make_empty_result(); return make_empty_result();
my_make_scrambled_password(tmp_value, res->ptr(), res->length());
str->set(m_hashed_password_buffer, m_hashed_password_buffer_len, str->set(tmp_value, SCRAMBLED_PASSWORD_CHAR_LENGTH, &my_charset_latin1);
default_charset());
return str; return str;
} }
char *Item_func_password:: char *Item_func_password::alloc(THD *thd, const char *password, size_t pass_len)
create_password_hash_buffer(THD *thd, const char *password, size_t pass_len)
{ {
char *buff= (char *) thd->alloc(SCRAMBLED_PASSWORD_CHAR_LENGTH+1);
if (buff)
{
String *password_str= new (thd->mem_root)String(password, thd->variables. String *password_str= new (thd->mem_root)String(password, thd->variables.
character_set_client); character_set_client);
check_password_policy(password_str); check_password_policy(password_str);
char *buff= NULL;
if (thd->variables.old_passwords == 0)
{
/* Allocate memory for the password scramble and one extra byte for \0 */
buff= (char *) thd->alloc(SCRAMBLED_PASSWORD_CHAR_LENGTH + 1);
my_make_scrambled_password_sha1(buff, password, pass_len);
}
#if defined(HAVE_OPENSSL)
else
{
/* Allocate memory for the password scramble and one extra byte for \0 */
buff= (char *) thd->alloc(CRYPT_MAX_PASSWORD_SIZE + 1);
my_make_scrambled_password(buff, password, pass_len); my_make_scrambled_password(buff, password, pass_len);
} }
#endif
return buff; return buff;
} }
......
...@@ -21,8 +21,6 @@ ...@@ -21,8 +21,6 @@
/* This file defines all string functions */ /* This file defines all string functions */
#include "crypt_genhash_impl.h"
#ifdef USE_PRAGMA_INTERFACE #ifdef USE_PRAGMA_INTERFACE
#pragma interface /* gcc class implementation */ #pragma interface /* gcc class implementation */
#endif #endif
...@@ -394,21 +392,16 @@ class Item_func_rtrim :public Item_func_trim ...@@ -394,21 +392,16 @@ class Item_func_rtrim :public Item_func_trim
class Item_func_password :public Item_str_ascii_func class Item_func_password :public Item_str_ascii_func
{ {
char m_hashed_password_buffer[CRYPT_MAX_PASSWORD_SIZE + 1]; char tmp_value[SCRAMBLED_PASSWORD_CHAR_LENGTH+1];
unsigned int m_hashed_password_buffer_len;
bool m_recalculate_password;
public: public:
Item_func_password(Item *a) :Item_str_ascii_func(a) Item_func_password(Item *a) :Item_str_ascii_func(a) {}
String *val_str_ascii(String *str);
void fix_length_and_dec()
{ {
m_hashed_password_buffer_len= 0; fix_length_and_charset(SCRAMBLED_PASSWORD_CHAR_LENGTH, default_charset());
m_recalculate_password= false;
} }
String *val_str_ascii(String *str);
void fix_length_and_dec();
const char *func_name() const { return "password"; } const char *func_name() const { return "password"; }
static char *alloc(THD *thd, const char *password, size_t pass_len); static char *alloc(THD *thd, const char *password, size_t pass_len);
static char *create_password_hash_buffer(THD *thd, const char *password,
size_t pass_len);
}; };
......
...@@ -67,7 +67,6 @@ ...@@ -67,7 +67,6 @@
#include <mysql.h> #include <mysql.h>
#include <my_rnd.h> #include <my_rnd.h>
#include <sha1.h> #include <sha1.h>
#include <crypt_genhash_impl.h>
/************ MySQL 3.23-4.0 authentication routines: untouched ***********/ /************ MySQL 3.23-4.0 authentication routines: untouched ***********/
...@@ -280,14 +279,13 @@ void make_password_from_salt_323(char *to, const ulong *salt) ...@@ -280,14 +279,13 @@ void make_password_from_salt_323(char *to, const ulong *salt)
**************** MySQL 4.1.1 authentication routines ************* **************** MySQL 4.1.1 authentication routines *************
*/ */
/* /**
Generate string of printable random characters of requested length Generate string of printable random characters of requested length.
SYNOPSIS
create_random_string() @param to[out] Buffer for generation; must be at least length+1 bytes
to OUT buffer for generation; must be at least length+1 bytes
long; result string is always null-terminated long; result string is always null-terminated
length IN how many random characters to put in buffer length[in] How many random characters to put in buffer
rand_st INOUT structure used for number generation rand_st Structure used for number generation
*/ */
void create_random_string(char *to, uint length, void create_random_string(char *to, uint length,
...@@ -374,23 +372,6 @@ my_crypt(char *to, const uchar *s1, const uchar *s2, uint len) ...@@ -374,23 +372,6 @@ my_crypt(char *to, const uchar *s1, const uchar *s2, uint len)
} }
#if defined(HAVE_OPENSSL)
void my_make_scrambled_password(char *to, const char *password,
size_t pass_len)
{
char salt[CRYPT_SALT_LENGTH + 1];
generate_user_salt(salt, CRYPT_SALT_LENGTH + 1);
my_crypt_genhash(to,
CRYPT_MAX_PASSWORD_SIZE,
password,
pass_len,
salt,
0);
}
#endif
/** /**
Compute two stage SHA1 hash of the password : Compute two stage SHA1 hash of the password :
...@@ -422,13 +403,13 @@ void compute_two_stage_sha1_hash(const char *password, size_t pass_len, ...@@ -422,13 +403,13 @@ void compute_two_stage_sha1_hash(const char *password, size_t pass_len,
The result of this function is used as return value from PASSWORD() and The result of this function is used as return value from PASSWORD() and
is stored in the database. is stored in the database.
SYNOPSIS SYNOPSIS
my_make_scrambled_password_sha1() my_make_scrambled_password()
buf OUT buffer of size 2*SHA1_HASH_SIZE + 2 to store hex string buf OUT buffer of size 2*SHA1_HASH_SIZE + 2 to store hex string
password IN password string password IN password string
pass_len IN length of password string pass_len IN length of password string
*/ */
void my_make_scrambled_password_sha1(char *to, const char *password, void my_make_scrambled_password(char *to, const char *password,
size_t pass_len) size_t pass_len)
{ {
uint8 hash_stage2[SHA1_HASH_SIZE]; uint8 hash_stage2[SHA1_HASH_SIZE];
...@@ -455,7 +436,7 @@ void my_make_scrambled_password_sha1(char *to, const char *password, ...@@ -455,7 +436,7 @@ void my_make_scrambled_password_sha1(char *to, const char *password,
void make_scrambled_password(char *to, const char *password) void make_scrambled_password(char *to, const char *password)
{ {
my_make_scrambled_password_sha1(to, password, strlen(password)); my_make_scrambled_password(to, password, strlen(password));
} }
...@@ -500,7 +481,7 @@ scramble(char *to, const char *message, const char *password) ...@@ -500,7 +481,7 @@ scramble(char *to, const char *message, const char *password)
null-terminated, reply and hash_stage2 must be at least SHA1_HASH_SIZE null-terminated, reply and hash_stage2 must be at least SHA1_HASH_SIZE
long (if not, something fishy is going on). long (if not, something fishy is going on).
SYNOPSIS SYNOPSIS
check_scramble_sha1() check_scramble()
scramble clients' reply, presumably produced by scramble() scramble clients' reply, presumably produced by scramble()
message original random string, previously sent to client message original random string, previously sent to client
(presumably second argument of scramble()), must be (presumably second argument of scramble()), must be
...@@ -514,7 +495,7 @@ scramble(char *to, const char *message, const char *password) ...@@ -514,7 +495,7 @@ scramble(char *to, const char *message, const char *password)
*/ */
my_bool my_bool
check_scramble_sha1(const uchar *scramble_arg, const char *message, check_scramble(const uchar *scramble_arg, const char *message,
const uint8 *hash_stage2) const uint8 *hash_stage2)
{ {
uint8 buf[SHA1_HASH_SIZE]; uint8 buf[SHA1_HASH_SIZE];
...@@ -532,13 +513,6 @@ check_scramble_sha1(const uchar *scramble_arg, const char *message, ...@@ -532,13 +513,6 @@ check_scramble_sha1(const uchar *scramble_arg, const char *message,
return test(memcmp(hash_stage2, hash_stage2_reassured, SHA1_HASH_SIZE)); return test(memcmp(hash_stage2, hash_stage2_reassured, SHA1_HASH_SIZE));
} }
my_bool
check_scramble(const uchar *scramble_arg, const char *message,
const uint8 *hash_stage2)
{
return check_scramble_sha1(scramble_arg, message, hash_stage2);
}
/* /*
Convert scrambled password from asciiz hex string to binary form. Convert scrambled password from asciiz hex string to binary form.
...@@ -567,3 +541,4 @@ void make_password_from_salt(char *to, const uint8 *hash_stage2) ...@@ -567,3 +541,4 @@ void make_password_from_salt(char *to, const uint8 *hash_stage2)
*to++= PVERSION41_CHAR; *to++= PVERSION41_CHAR;
octet2hex(to, (const char*) hash_stage2, SHA1_HASH_SIZE); octet2hex(to, (const char*) hash_stage2, SHA1_HASH_SIZE);
} }
...@@ -11419,13 +11419,20 @@ static ulong parse_client_handshake_packet(MPVIO_EXT *mpvio, ...@@ -11419,13 +11419,20 @@ static ulong parse_client_handshake_packet(MPVIO_EXT *mpvio,
Cast *passwd to an unsigned char, so that it doesn't extend the sign for Cast *passwd to an unsigned char, so that it doesn't extend the sign for
*passwd > 127 and become 2**32-127+ after casting to uint. *passwd > 127 and become 2**32-127+ after casting to uint.
*/ */
uint passwd_len= thd->client_capabilities & CLIENT_SECURE_CONNECTION ? uint passwd_len;
(uchar)(*passwd++) : strlen(passwd); if (!(thd->client_capabilities & CLIENT_SECURE_CONNECTION))
passwd_len= strlen(passwd);
else if (!(thd->client_capabilities & CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA))
passwd_len= (uchar)(*passwd++);
else
passwd_len= safe_net_field_length_ll((uchar**)&passwd,
net->read_pos + pkt_len - (uchar*)passwd);
db= thd->client_capabilities & CLIENT_CONNECT_WITH_DB ? db= thd->client_capabilities & CLIENT_CONNECT_WITH_DB ?
db + passwd_len + 1 : 0; db + passwd_len + 1 : 0;
if (passwd + passwd_len + test(db) > (char *)net->read_pos + pkt_len) if (passwd == NULL ||
passwd + passwd_len + test(db) > (char *)net->read_pos + pkt_len)
return packet_error; return packet_error;
/* strlen() can't be easily deleted without changing protocol */ /* strlen() can't be easily deleted without changing protocol */
......
...@@ -9753,7 +9753,7 @@ function_call_conflict: ...@@ -9753,7 +9753,7 @@ function_call_conflict:
| PASSWORD '(' expr ')' | PASSWORD '(' expr ')'
{ {
Item* i1; Item* i1;
if (thd->variables.old_passwords == 1) if (thd->variables.old_passwords)
i1= new (thd->mem_root) Item_func_old_password($3); i1= new (thd->mem_root) Item_func_old_password($3);
else else
i1= new (thd->mem_root) Item_func_password($3); i1= new (thd->mem_root) Item_func_password($3);
...@@ -14789,18 +14789,10 @@ text_or_password: ...@@ -14789,18 +14789,10 @@ text_or_password:
TEXT_STRING { $$=$1.str;} TEXT_STRING { $$=$1.str;}
| PASSWORD '(' TEXT_STRING ')' | PASSWORD '(' TEXT_STRING ')'
{ {
if ($3.length == 0) $$= $3.length ? thd->variables.old_passwords ?
$$= $3.str; Item_func_old_password::alloc(thd, $3.str, $3.length) :
else Item_func_password::alloc(thd, $3.str, $3.length) :
switch (thd->variables.old_passwords) { $3.str;
case 1: $$= Item_func_old_password::
alloc(thd, $3.str, $3.length);
break;
case 0:
case 2: $$= Item_func_password::
create_password_hash_buffer(thd, $3.str, $3.length);
break;
}
if ($$ == NULL) if ($$ == NULL)
MYSQL_YYABORT; MYSQL_YYABORT;
} }
...@@ -15400,7 +15392,7 @@ grant_user: ...@@ -15400,7 +15392,7 @@ grant_user:
(char *) thd->alloc(SCRAMBLED_PASSWORD_CHAR_LENGTH+1); (char *) thd->alloc(SCRAMBLED_PASSWORD_CHAR_LENGTH+1);
if (buff == NULL) if (buff == NULL)
MYSQL_YYABORT; MYSQL_YYABORT;
my_make_scrambled_password_sha1(buff, $4.str, $4.length); my_make_scrambled_password(buff, $4.str, $4.length);
$1->password.str= buff; $1->password.str= buff;
$1->password.length= SCRAMBLED_PASSWORD_CHAR_LENGTH; $1->password.length= SCRAMBLED_PASSWORD_CHAR_LENGTH;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment