Mysql源码学习――用户认证原理与实现(二)

2014-11-24 10:35:16 · 作者: · 浏览: 1
接的主机地址,这样也是为了提高安全性吧。那如果我想一个用户在任何地址都可以进行登录岂不是要设置很多地址?Mysql提供了通配符,可以设置Host字段为*,这就代表可以匹配任何Host。具体看下这三行的意思,这三行的密码均为空。针对root用户,不需要输入密码,客户端的地址为本机。第三行的用户名为空,Host为localhost,说明本地的任何用户均可以进行登录,即使是个不存在的用户也可以登录成功,但是仅限于登录,没有其他相关的权限,无法进行实际操作。

二、源码跟踪

在Connection Manager中提到了login_connection函数用于检查用户名和密码等相关信息,其源码如下(重点的函数代码

会着色):

static bool login_connection(THD *thd)

{

NET *net= &thd->net;

int error;

DBUG_ENTER("login_connection");

DBUG_PRINT("info", ("login_connection called by thread %lu",

thd->thread_id));

/* Use "connect_timeout" value during connection phase */

my_net_set_read_timeout(net, connect_timeout);

my_net_set_write_timeout(net, connect_timeout);

error= check_connection(thd); //此处是验证的具体函数

net_end_statement(thd);

if (error)

{ // Wrong permissions

#ifdef __NT__

if (vio_type(net->vio) == VIO_TYPE_NAMEDPIPE)

my_sleep(1000); /* must wait after eof() */

#endif

statistic_increment(aborted_connects,&LOCK_status);

DBUG_RETURN(1);

}

/* Connect completed, set read/write timeouts back to default */

my_net_set_read_timeout(net, thd->variables.net_read_timeout);

my_net_set_write_timeout(net, thd->variables.net_write_timeout);

DBUG_RETURN(0);

}

  

此函数主要是功能是调用函数check_connection进行用户认证,由于函数check_connection过长,对其进行简化,如下所示:

static int check_connection(THD *thd)

{

uint connect_errors= 0;

NET *net= &thd->net;

ulong pkt_len= 0;

char *end;

DBUG_PRINT("info",

("New connection received on %s", vio_description(net->vio)));

#ifdef SIGNAL_WITH_VIO_CLOSE

thd->set_active_vio(net->vio);

#endif

if (!thd->main_security_ctx.host) // If TCP/IP connection

{

char ip[30];

if (vio_peer_addr(net->vio, ip, &thd->peer_port))

{

my_error(ER_BAD_HOST_ERROR, MYF(0), thd->main_security_ctx.host_or_ip);

return 1;

}

if (!(thd->main_security_ctx.ip= my_strdup(ip,MYF(MY_WME))))

return 1; /* The error is set by my_strdup(). */

thd->main_security_ctx.host_or_ip= thd->main_security_ctx.ip;

vio_in_addr(net->vio,&thd->remote.sin_addr);

if (!(specialflag & SPECIAL_NO_RESOLVE))

{

vio_in_addr(net->vio,&thd->remote.sin_addr);

thd->main_security_ctx.host=

ip_to_hostname(&thd->remote.sin_addr, &connect_errors);

/* Cut very long hostnames to avoid possible overflows */

if (thd->main_security_ctx.host)

{

if (thd->main_security_ctx.host != my_localhost)

thd->main_security_ctx.host[min(strlen(thd->main_security_ctx.host),

HOSTNAME_LENGTH)]= 0;

thd->main_security_ctx.host_or_ip= thd->main_security_ctx.host;

}

if (connect_errors > max_connect_errors)

{

my_error(ER_HOST_IS_BLOCKED, MYF(0), thd->main_security_ctx.host_or_ip);

return 1;

}

}

...

if (acl_check_host(thd->main_security_ctx.host, thd->main_security_ctx.ip))//此处验证主机名或IP是否存在

{

my_error(ER_HOST_NOT_PRIVILEGED, MYF(0),

thd->main_security_ctx.host_or_ip);

return 1;

}

}

else /* Hostname given means that the connection was on a socket */