内存 BIO 的 SSL_pending 功能?

问题描述 投票:0回答:1

我使用 2 个内存 BIO (BIO_s_mem) 来通过 Winsock 实现异步功能。

ssl = SSL_new(this->ctx);

ssl_input = BIO_new(BIO_s_mem());
ssl_output = BIO_new(BIO_s_mem());

SSL_set_bio(ssl, ssl_input, ssl_output);

将套接字接收到的数据写入输入 BIO (

BIO_write(ssl_input, ...
) 不会让 OpenSSL 更新其内部状态。因此,在写入 BIO 后调用像 SSL_pending 这样的函数具有相同的结果,就好像我根本没有写入 BIO 一样。 内部状态仅在调用 SSL_read 时更新,但我可能只是还不想读取。

我想到的一个可能的解决方案是使用缓冲区大小非常小的 SSL_peek (以避免浪费地复制大量我不会使用的数据),但我还没有找到理由相信它会消耗 BIO 中的所有数据。即使它有效,听起来也是错误的做法。

我确实意识到,当我确实需要时调用 SSL_read 最终将是透明的。它将从 BIO 中读取数据,进行所需的任何处理,然后返回数据 - 我知道。然而,我仍然希望在我的包装类中具有 SSL_pending 的功能。并非每次对 BIO 的写入都会产生缓冲数据(即握手、重新协商、心跳),了解是否有任何数据很有用,而无需隐式地将其拉出(如果有)。

openssl
1个回答
0
投票

SSL_pending 的工作方式似乎与我最初的想法不同。即使使用阻塞套接字,返回值也仅表示 SSL 缓冲区中“left”的数据。为了让数据首先进入 ssl 缓冲区,需要发生 SSL_read - 无论您是否有内存 Bio 或其他东西。

SSL 对象是一个状态机,只有当您调用 

SSL_read

SSL_write
时,其齿轮才会转动。内存 BIO 没有机制让 SSL 状态机处理其内容 - 事实上,BIO 甚至不知道 SSL 状态机,它们只是被 SSL 状态机使用。
写入内存 BIO 只会将数据放入其缓冲区中 - 执行路径永远不会与 ssl 对象中的任何内容连接。从源代码来看,似乎没有任何指针可以指向它。


我想到的一个可能的解决方案是使用缓冲区大小非常小的 SSL_peek

更好的解决方案是在
BIO_write(ssl_input)

后面加上

SSL_read(ssl, 0, 0)
它使用缓冲区中的内容更新 SSL 状态,不复制任何数据,并且由于一次只能读取一条记录(并且在完全接收到记录之前无法读取数据),因此我们需要不用担心留下未处理的数据。

© www.soinside.com 2019 - 2024. All rights reserved.