文档章节

sql server 通过sql server 协议进行登录的解析

harris2016
 harris2016
发布于 2016/10/19 15:41
字数 1813
阅读 392
收藏 5

  为了在oneproxy-monitor中实现sql server的前后端登录分离,经过一段时间的研究终于把sql server的登录搞定了。目前可以做到前端通过一个密码连接到中间件oneproxy-for-sqlserver(oneproxy-monitor的sqlserver版本)。oneproxy-for-sqlserver再通过数据库密码登录到后端sql server数据库,再实现前后端数据的直接转发功能。

    sql server登录过程的数据包交互情况如下图所示,登录过程中从大体上来说指涉及到两个请求包和两个响应数据包。其中prelogin数据包是为了本次连接把客户端的环境信息发送到服务端,这个数据包中包括:客户端的版本信息,是否要求加密等8类数据并且以0xff来结束,在0xff结束后在放置前面各种类型的具体数据内容。可以参见MSDN。prelogin的响应包是对应类型的响应情况。这一步比较简单,可以直接进行解包和回复响应包。

    目前我研究的对象是sql server 2016,从sql server的官方文档可以知道,不管是否配置使用ssl还是不使用ssl,在登录的过程中都会 使用ssl来保护login7的数据包,防止中间人攻击。在login7中包含了用户的用户名,密码,以及前端应用信息,tds版本,客户端能够接收的包大小,客户端进程ID, 连接ID等。可见这个数据包是登录过程中关键的数据包。只要搞定这个数据包登录过程就能够搞定了。

   要解析出login7包中的内容,就需要在中间件中实现ssl的服务端环境。通过ssl来对数据进行解密和加密login7数据包。要实现ssl端的服务端环境,则需要解决两个问题:

1. ssl服务端的证书问题

2. 解决ssl的加密数据包中增加和去掉sqlserver的包头的问题

解决ssl服务端的证书问题

    开始以为sqlserver会在主机上面生成证书,并且保存到指定的文件中。于是在主机上面搜索sql server的证书,结果...,然后没有结果了。于是阅读msdn上面的文章,才了解到sql server当用户设置不使用ssl加密时,会生成自签名证书。但是没有说到是否生成证书文件,在stackoverflow上面了解到是没有生成证书文件,只是在sql server启动时内存中生成证书信息,把证书信息保存在内存中的。

    于是通过阅读openssl的源代码了解内存中证书的使用方法,以及使用openssl api生成证书的实现方式。其中openssl api生成证书的实现可以参见开源软件ssl-cert-generator-lib。在通过如下两个函数把证书和私钥载入到ssl上下文中。

int SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey);
int SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x);

需要注意的是不能直接使用ssl-cert-generator-lib中返回的public_key_pem和private_key_pem来设置,否则会得到wrong tag的错误。

解决ssl加密包头的问题

    通过阅读msdn的文档可以知道,并不是把login7数据包直接通过ssl来发送即可,还需要在加密后的数据包中增加一个sql server包的头信息。通过阅读openssl发数据的代码(如下所示),可以知道在发送的数据会先调用回调函数,只要设置这个回调函数就可以在发送加密数据包之前增加sql server包的头信息。

int BIO_read(BIO *b, void *out, int outl)
{
    int i;
    long (*cb) (BIO *, int, const char *, int, long, long);

    if ((b == NULL) || (b->method == NULL) || (b->method->bread == NULL)) {
        BIOerr(BIO_F_BIO_READ, BIO_R_UNSUPPORTED_METHOD);
        return (-2);
    }

    cb = b->callback;
    if ((cb != NULL) &&
        ((i = (int)cb(b, BIO_CB_READ, out, outl, 0L, 1L)) <= 0))
        return (i);

    if (!b->init) {
        BIOerr(BIO_F_BIO_READ, BIO_R_UNINITIALIZED);
        return (-2);
    }

    i = b->method->bread(b, out, outl);

    if (i > 0)
        b->num_read += (unsigned long)i;

    if (cb != NULL)
        i = (int)cb(b, BIO_CB_READ | BIO_CB_RETURN, out, outl, 0L, (long)i);
    return (i);
}

从上面代码中能够了解到只要实现BIO结构中的callback即可。而这个callback正是SSL结构中的rbio指针的callback。并且openssl提供了如下的函数来设置这个回调函数:

void BIO_set_callback(BIO *b,
                      long (*callback) (struct bio_st *, int, const char *,
                                        int, long, long));

现在主要来讲解回调函数的定义情况,下面是oneproxy-monitor中针对sqlserver的回调函数指针的定义。

typedef long (*handle_data_callback) (struct bio_st *bio, int oper, const char *data, int dataLen, long argl, long ret);

需要注意的是oper的值,其中oper的可以取值:BIO_CB_WRITE,BIO_CB_READ,BIO_CB_RETURN等,当发送数据的时候oper将是BIO_CB_WRITE,发送完毕后oper的值为BIO_CB_WRITE|BIO_CB_RETURN.当开始读取数据时oper是BIO_CB_READ,读取完毕后BIO_CB_RETURN.

下面来说一个有趣的事情(见下面ssl结构的部分代码):先说明我使用的是openssl-1.0.2e版本,从这个结构中可以了解到ssl结构中提供了BIO *rbio, BIO* wbio以及BIO* bbio.我开始以为openssl是通过bbio来进行读写数据的,于是通过BIO_set_callback来设置bbio的回调函数,结果直接core了。通过阅读代码才知道原来这个啃爹的尽然为NULL,并没有设置。这个让我很不能理解openssl为啥这么干,这不是明显的站着资源不干活嘛。

struct ssl_st {
    /*
     * protocol version (one of SSL2_VERSION, SSL3_VERSION, TLS1_VERSION,
     * DTLS1_VERSION)
     */
    int version;
    /* SSL_ST_CONNECT or SSL_ST_ACCEPT */
    int type;
    /* SSLv3 */
    const SSL_METHOD *method;
    /*
     * There are 2 BIO's even though they are normally both the same.  This
     * is so data can be read and written to different handlers
     */
#  ifndef OPENSSL_NO_BIO
    /* used by SSL_read */
    BIO *rbio;
    /* used by SSL_write */
    BIO *wbio;
    /* used during session-id reuse to concatenate messages */
    BIO *bbio;
#  else
    /* used by SSL_read */
    char *rbio;
    /* used by SSL_write */
    char *wbio;
    char *bbio;
#  endif

第二个有趣的事情是:由于sql server在读和写的时候都需要对包头进行操作。读的时候需要去掉sql server的额外包头,在写的时候要增加额外包头。于是看了BIO_set_callback的函数后秒懂,不就是设置两个回调函数嘛?于是匆匆写了一个写的回调函数,一个读的回调函数,并且通过BIO_set_callback函数设置到对应的BIO上面,结果测试发现先设置的回调函数总是失效。这个坑爹的,连个回调函数都设置不成功了。把自己的代码阅读了n遍发现没有错误呀,最后再次阅读openssl的代码,发现rbio和wbio居然是同一个结构。在通过BIO_set_callback设置rbio的回调函数的同时也就是把wbio的回调函数给设置了,反之也是。这个地方又体现了openssl坑爹的一面。居然设置wbio的回调函数把rbio的回调函数也设置了。这个怎么看怎么怪。为啥不把bbio也指向rbio和wbio的结构 呢,这样通过设置bbio的回调函数来设置读和写的回调函数不是更加合理么?

更多信息,请关注oneproxy-monitor

© 著作权归作者所有

harris2016
粉丝 10
博文 54
码字总数 30661
作品 0
杭州
程序员
私信 提问
SQL 2000 开启远程

配置sql server 2000以允许远程访问 配置sql server 2000以允许远程访问 适合故障: 1. 用sql企业管理器能访问sql server 2000(因为它是采用命名管道(named pipes)方式进行方式),但用ado.net...

fengfaling2013
2015/09/08
0
0
远程连接局域网内的sql server 无法连接 错误与解决方法

第一个错误"SQL Server 不存在或访问被拒绝"通常是最复杂的,错误发生的原因比较多,需要检查的方面也比较多 。一般说来,有以下几种可能性:   1、SQL Server名称或IP地址拼写有误;   ...

Andrewniu
2018/10/19
0
0
Sql Server 数据库之间如何进行跨网远程连接访问

场景说明   现在有一台A电脑和一台B电脑,两台电脑都安装了Sql Server数据库,两台电脑不在一个局域网(我们考虑的是不同网络的两台数据库连接),比如A电脑在公司,B电脑在家里,现在我要在...

Andrewniu
01/10
0
0
跨网远程连接SQLSERVER不同实例不同端口

现在有一台A电脑和一台B电脑,A是公司的服务器,安装了两个数据库实例(Sql Server 2012 和Sql Server2008 R2),B电脑在家,安装了Sql Server数据库两台电脑不在一个局域网(我们考虑的是不同...

Andrewniu
05/09
0
0
Windows身份验证模式和混合模式的区别

某日,A君问起Windows身份验证模式和混合模式验证的区别与优缺时,根据安全性的考虑,按照到了此文作为参考,学习下~ 在安装过程中,必须为数据库引擎选择身份验证模式。 可供选择的模式有两...

Cnlouds
2013/10/30
0
0

没有更多内容

加载失败,请刷新页面

加载更多

掌握生成对抗网络(GANs),召唤专属二次元老婆(老公)不是梦

全文共6706字,预计学习时长12分钟或更长 近日,《狮子王》热映,其逼真的外形,几乎可以以假乱真,让观众不禁大呼:awsl,这也太真实了吧! 实体模型、CGI动画、实景拍摄、VR等技术娴熟运用...

读芯术
27分钟前
1
0
C#经典面试题100道

1. .NET和C#有什么区别 答:.NET一般指 .NET FrameWork框架,它是一种平台,一种技术。 C#是一种编程语言,可以基于.NET平台的应用。 2.一列数的规则如下: 1、1、2、3、5、8、13、21、34......

元歌
30分钟前
0
0
重磅!容器集群监控利器 阿里云Prometheus 正式免费公测

Prometheus 作为容器生态下集群监控的首选方案,是一套开源的系统监控报警框架。它启发于 Google 的 borgmon 监控系统,并于 2015 年正式发布。2016 年,Prometheus 正式加入 Cloud Native C...

阿里云云栖社区
31分钟前
1
0
LeetCode 160: 相交链表 Intersection of Two Linked Lists

爱写Bug(ID:iCodeBugs) 编写一个程序,找到两个单链表相交的起始节点。 Write a program to find the node at which the intersection of two singly linked lists begins. 如下面的两个链...

iCodeBugs
33分钟前
2
0
hadoop yarn漏洞 8088端口进入挖矿病毒处理记录

早上发现服务器cpu使用异常 进程如图所示 按照挖矿病毒的套路 肯定是定时任务不停地执行脚本 遂查看定时任务 进入/var/spool/cron 查看定时任务 发现里面有一个root文件 定时任务每分钟执行一...

詹姆斯-高斯林
37分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部