C语言 在OpenSSL中恢复TLS 1.3会话



我正在使用TLS 1.3客户端,并尝试支持会话恢复。我设法用下面的方法做了这件事:

当服务器发送NewSessionTicket时,我有一个回调函数new_session_cb_func(SSL *ssl, SSL_SESSION *session)

  1. 创建文件。BIO *stmp = BIO_new_file(filepath, "w")
  2. 将会话写入li。PEM_write_bio_SSL_SESSION(stmp, session)

当客户端想要恢复会话时,它使用PskSessionResume(SSL *ssl)函数:

  1. 打开存储会话的文件。BIO *stmp = BIO_new_file(filepath, "r")
  2. 从文件。SSL_SESSION *sess = PEM_read_bio_SSL_SESSION(stmp, NULL, 0, NULL)
  3. 恢复会话。SSL_set_session(ssl, sess)

目前运行正常

我试图更改代码,使会话将保存在内存中而不是文件中。

new_session_cb_func(SSL *ssl, SSL_SESSION *session):

  1. 将会话保存到一个全局变量。SSL_SESSION *prev_sess = session

PskSessionResume(SSL *ssl):

  1. 确保prev_sess != NULL.
  2. 恢复会话。SSL_set_session(ssl, prev_sess)

由于某些原因,更改后恢复不工作。SSL_set_session返回1,但客户端没有发送预共享密钥,因此进行一次完整的握手。

似乎传递给回调的SESSION的指针不希望保持原样。实际上,在存储会话时,您希望复制结构的整个内容,而不仅仅是跟踪其地址。

当你把会话保存在一个文件中时,这个文件是用结构的内容而不是结构的地址来写的。

我强烈怀疑在程序执行期间(在恢复之前),您跟踪的指针被释放并以某种方式重新使用。也就是说,当您想要恢复会话并使用备份的SESSION指针时,它不再指向有效/一致的内存数据。

这就是为什么会话不能按预期恢复,进程从头开始。

这种情况的解决方案是将全局变量的类型从SESSION *prev_sess;更改为SESSION prev_sess,并在回调中使用prev_sess = *session;保存会话。这样,就保留了结构体内容的副本,而不是指针的副本。

如果一切顺利,恢复会议将进行得很顺利!

编辑:

API提供了复制会话上下文的函数:SSL_SESSION_dup(SSL_SESSION *session)。您可能希望使用它来复制传递给回调的当前session

引用自文档链接:

SSL对象可能正在使用SSL_SESSION对象;由于会话可以被重用,多个SSL对象可以同时使用一个SSL_SESSION对象。因此,保持引用计数(使用信息)正确并且不删除仍在使用的SSL_SESSION对象是至关重要的,因为这可能会由于悬空指针而导致程序失败。

从那里,似乎你可以保持原来的指针,只要你还标记它与SSL_SESSION_up_ref的一次使用。这应该保证只要你需要它,结构就永远不会被释放。

最新更新