MySQL · 源码分析 · mysql认证阶段漫游

本文涉及的产品
云原生数据库 PolarDB 分布式版,标准版 2核8GB
云数据库 RDS SQL Server,基础系列 2核4GB
RDS SQL Server Serverless,2-4RCU 50GB 3个月
推荐场景:
简介: client发起一个连接请求, 到拿到server返回的ok包之间, 走三次握手, 交换了[不可告人]的验证信息, 这期间mysql如何完成校验工作?过程(三次握手)信息是如何加密的client:hash_stage1 = sha1(password)hash_stage2 = sha1(hash_stage1)reply = sha1(scramble, hash_sta

client发起一个连接请求, 到拿到server返回的ok包之间, 走三次握手, 交换了[不可告人]的验证信息, 这期间mysql如何完成校验工作?

过程(三次握手)

没加滤镜的三次握手

信息是如何加密的

client:

hash_stage1 = sha1(password)
hash_stage2 = sha1(hash_stage1)
reply = sha1(scramble, hash_stage2) ^ hash_stage1

server: (逻辑位于sql/password.c:check_scramble_sha1中, 下文亦有提及)

// mysql.user表中, 对应user的passwd实际上是hash_stage2
res1 = sha1(scramble, hash_stage2)
hash_stage1 = reply ^ res1
hash_stage2_reassured = sha1(hash_stage1)
再根据hash_stage2_reassured == hash_stage2(from mysql.user)是否一致来判定是否合法

涉事函数们

如图, client发起连接请求, server创建新的线程, 并进入acl_authenticate(5.7位于sql/auth/sql_authentication.cc, 5.6位于sql/sql_acl.cc)函数完成信息验证, 并把包里读出的信息更新到本线程.

流程堆栈:

#0  parse_client_handshake_packet 
#1  server_mpvio_read_packet 
#2  native_password_authenticate
#3  do_auth_once 
#4  acl_authenticate 
#5  check_connection 
#6  login_connection 
#7  thd_prepare_connection
#8  do_handle_one_connection

接下来考察这些函数中做了哪些事.
check_connection(sql/sql_connect.cc)
当接收到client的建连接请求时, 进入check_connection, 先对连接本身上下文分析(socket, tcp/ip的v4/6 哇之类的)
当然你用very long的host连进来, 也会在这里被cut掉防止overflow.
不合法的ip/host也会在这里直接返回, 如果环境ok, 就进入到acl_authenticate的逻辑中
acl_authenticate:
初始化MPVIO_EXT, 用于保存验证过程的上下文; 字符集, 挑战码, …的坑位, 上锁, 根据command进行分派, (新建链接为COM_CONNECT

COM_CONNECT下会进入函数do_auth_once(), 返回值直接决定握手成功与否.
先对authentication plugin做判定, 咱们这里基于”mysql_native_password”的情况

if (plugin)
  {
    st_mysql_auth *auth= (st_mysql_auth *) plugin_decl(plugin)->info;
    res= auth->authenticate_user(mpvio, &mpvio->auth_info);  
    ...

在mysql_native_password时会进入native_password_authenticate 逻辑:

  /* generate the scramble, or reuse the old one */
  if (mpvio->scramble[SCRAMBLE_LENGTH])
    create_random_string(mpvio->scramble, SCRAMBLE_LENGTH, mpvio->rand);

  /* send it to the client */
  if (mpvio->write_packet(mpvio, (uchar*) mpvio->scramble, SCRAMBLE_LENGTH + 1)) 
    DBUG_RETURN(CR_AUTH_HANDSHAKE);

  /* read the reply with the encrypted password */
  if ((pkt_len= mpvio->read_packet(mpvio, &pkt)) < 0)                                                                                        
    DBUG_RETURN(CR_AUTH_HANDSHAKE);
  DBUG_PRINT("info", ("reply read : pkt_len=%d", pkt_len));

可见这里才生成了挑战码并发送到client, 再调用mpvio->read_packet等待client回包,
进入server_mpvio_read_packet,
这里的实现则调用常见的my_net_read读包,
当拿到auth包时, 逻辑分派到parse_client_handshake_packet, 对包内容进行parse, 这里会根据不同client protocol, 去掉头和尾, 还对client是否设置了ssl做判定. 接着:

  if (mpvio->client_capabilities & CLIENT_SECURE_CONNECTION)                                                                                 
  {
    /*    
      Get the password field.
    */
    passwd= get_length_encoded_string(&end, &bytes_remaining_in_packet,
                                      &passwd_len);
  }
  else  
  {
    /*    
      Old passwords are zero terminatedtrings.
    */
    passwd= get_string(&end, &bytes_remaining_in_packet, &passwd_len);
  }
  ...

在拿到了client发来的加密串(虽然叫passwd), 暂时存放在内存中, 返回native_password_authenticate,
当判定为需要做password check时(万一有人不设置密码呢), 进入check_scramble, 这个函数中才实现了对密码的验证:

// server decode回包中的加密信息
// 把上面提到的三个公式包在函数中
my_bool
check_scramble_sha1(const uchar *scramble_arg, const char *message,
                    const uint8 *hash_stage2)
{
  uint8 buf[SHA1_HASH_SIZE];
  uint8 hash_stage2_reassured[SHA1_HASH_SIZE];

  /* create key to encrypt scramble */
  compute_sha1_hash_multi(buf, message, SCRAMBLE_LENGTH,
                          (const char *) hash_stage2, SHA1_HASH_SIZE);
  /* encrypt scramble */
  my_crypt((char *) buf, buf, scramble_arg, SCRAMBLE_LENGTH);

  /* now buf supposedly contains hash_stage1: so we can get hash_stage2 */
  compute_sha1_hash(hash_stage2_reassured, (const char *) buf, SHA1_HASH_SIZE);

  return MY_TEST(memcmp(hash_stage2, hash_stage2_reassured, SHA1_HASH_SIZE));
}

native_password_authenticate拿到check_scamble的返回值, 返回OK,
再返回到acl_authenticate, 讲mpvio中环境信息更新到线程信息THD中, successful login~

(所以可以魔改这块代码搞事, 密码什么的, 权限什么的….
(我就说说, 别当真

相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
SQL 存储 关系型数据库
MySQL · 引擎特性 · InnoDB redo log漫游
前言 InnoDB 有两块非常重要的日志,一个是undo log,另外一个是redo log,前者用来保证事务的原子性以及InnoDB的MVCC,后者用来保证事务的持久性。 和大多数关系型数据库一样,InnoDB记录了对数据文件的物理更改,并保证总是日志先行,也就是所谓的WAL,即在持久化数据文
9467 2
|
存储 SQL 关系型数据库
MySQL · 引擎特性 · InnoDB undo log 漫游
本文是对整个Undo生命周期过程的阐述,代码分析基于当前最新的MySQL5.7版本。本文也可以作为了解整个Undo模块的代码导读。由于涉及到的模块众多,因此部分细节并未深入。 前言 Undo log是InnoDB MVCC事务特性的重要组成部分。当我们对记录做了变更操作时就会产生undo记录
3692 0
|
25天前
|
关系型数据库 MySQL 数据库连接
数据库连接工具连接mysql提示:“Host ‘172.23.0.1‘ is not allowed to connect to this MySQL server“
docker-compose部署mysql8服务后,连接时提示不允许连接问题解决
|
11天前
|
关系型数据库 MySQL 数据库
Docker Compose V2 安装常用数据库MySQL+Mongo
以上内容涵盖了使用 Docker Compose 安装和管理 MySQL 和 MongoDB 的详细步骤,希望对您有所帮助。
88 42
|
2天前
|
关系型数据库 MySQL 网络安全
如何排查和解决PHP连接数据库MYSQL失败写锁的问题
通过本文的介绍,您可以系统地了解如何排查和解决PHP连接MySQL数据库失败及写锁问题。通过检查配置、确保服务启动、调整防火墙设置和用户权限,以及识别和解决长时间运行的事务和死锁问题,可以有效地保障应用的稳定运行。
41 25
|
29天前
|
缓存 关系型数据库 MySQL
【深入了解MySQL】优化查询性能与数据库设计的深度总结
本文详细介绍了MySQL查询优化和数据库设计技巧,涵盖基础优化、高级技巧及性能监控。
245 0
|
2月前
|
存储 Oracle 关系型数据库
数据库传奇:MySQL创世之父的两千金My、Maria
《数据库传奇:MySQL创世之父的两千金My、Maria》介绍了MySQL的发展历程及其分支MariaDB。MySQL由Michael Widenius等人于1994年创建,现归Oracle所有,广泛应用于阿里巴巴、腾讯等企业。2009年,Widenius因担心Oracle收购影响MySQL的开源性,创建了MariaDB,提供额外功能和改进。维基百科、Google等已逐步替换为MariaDB,以确保更好的性能和社区支持。掌握MariaDB作为备用方案,对未来发展至关重要。
73 3
|
2月前
|
安全 关系型数据库 MySQL
MySQL崩溃保险箱:探秘Redo/Undo日志确保数据库安全无忧!
《MySQL崩溃保险箱:探秘Redo/Undo日志确保数据库安全无忧!》介绍了MySQL中的三种关键日志:二进制日志(Binary Log)、重做日志(Redo Log)和撤销日志(Undo Log)。这些日志确保了数据库的ACID特性,即原子性、一致性、隔离性和持久性。Redo Log记录数据页的物理修改,保证事务持久性;Undo Log记录事务的逆操作,支持回滚和多版本并发控制(MVCC)。文章还详细对比了InnoDB和MyISAM存储引擎在事务支持、锁定机制、并发性等方面的差异,强调了InnoDB在高并发和事务处理中的优势。通过这些机制,MySQL能够在事务执行、崩溃和恢复过程中保持
123 3

相关产品

  • 云数据库 RDS MySQL 版
  • 推荐镜像

    更多