注意
本文档适用于 Ceph 开发版本。
Cephx协议的会话认证
Peter Reiher
最初的 Cephx 协议将客户端认证给认证器,并设置一个会话密钥用于客户端认证它需要与之通信的服务器。然而,它并没有认证客户端和服务之间正在进行的消息。基于他们共享一个密钥的事实,这些正在进行的会话消息可以通过使用密钥对消息进行签名来轻松地进行认证。
本文档描述了对代码的更改,这些更改允许进行此类正在进行的会话认证。这些更改允许未来的更改,以允许其他认证协议(以及现有的空 NONE 和未知 UNKNOWN 协议)处理签名,但在编写时,实际上只有 Cephx 协议会签名。
简介
这段代码在 Cephx 协议完成后才会生效。在这个时候,客户端和服务器共享一个密钥。这个密钥将用于认证。对于其他协议,可能存在也可能不存在这样的密钥,并且实际用于执行签名的过程可能不同,因此代码被编写得具有通用性。
这里的“会话”由一个已建立的管道表示。对于此类管道,应该有一个附加到管道的结构。每当要在管道上发送消息时,将调用处理此类会话安全签名的代码。在管道的另一端,将调用检查此类会话安全的消息签名的代码。未能通过签名检查的消息将不会被进一步处理。这意味着发送方最好与接收方就使用的会话安全达成一致,否则它们之间的消息将一律被丢弃。session\_security
structure attached to the pipe. Whenever a message is to be sent on the
pipe, code that handles the signature for this kind of session security will be called. On the
other end of the pipe, code that checks this kind of session security’s message signatures will
be called. Messages that fail the signature check will not be processed further. That implies
that the sender had better be in agreement with the receiver on the session security being used,
since otherwise messages will be uniformly dropped between them.
该代码还准备处理会话消息的加密和解密,这将为签名提供的完整性增加机密性。尽管目前没有协议对正在进行的会话消息进行加密。
为了使此功能正常工作,需要执行几个步骤。首先,发送方和接收方必须成功运行 Cephx 协议以建立共享密钥。他们必须将密钥存储在管道稍后可以访问的地方,以允许使用它对消息进行签名。发送的消息必须被签名,接收的消息必须对其签名进行检查。
签名可以以多种方式计算,但目前其大小限制为 64 位。消息的签名放置在其尾部,在一个称为sig
.
的字段中。Cephx 中的签名代码可以在运行时打开和关闭,使用一个称为cephx\_sign\_messages
的 Ceph 布尔选项。它目前默认设置为 false,因此不会对任何消息进行签名。必须将其更改为 true 以导致计算和检查签名。
存储密钥
密钥需要在发送端创建签名并在接收端检查签名时使用。在未来,如果非对称加密是一个选项,那么可能需要存储两个密钥(一个用于管道的这一端,另一个用于另一端)。此时,双向的消息将使用相同的密钥进行签名,因此只需要保存该密钥。
密钥在管道建立时保存。在客户端侧,这发生在connect()
中,它位于msg/Pipe.cc
中。密钥是从 Cephx 协议的运行中获得的,这导致成功检查的授权结构。如果存在这样的授权器,代码将调用get\_auth\_session\_handler()
来创建一个新的认证会话处理程序并将其存储在管道数据结构中。在服务器侧,在验证客户端提供的授权器后,会执行类似的事情。accept()
after the authorizer provided by the client has been verified.
一旦在连接的任一端完成这些操作,会话认证就可以开始。
这些例程 (connect()
和accept()
) 也用于处理正在设置新会话的情况。在这个阶段,还没有创建授权器,所以没有密钥。在调用签名代码的代码中,当CEPH\_AUTH\_UNKNOWN
协议正在使用时,会跳过这些调用。此协议标签位于会话中的预授权消息上,表示正在进行认证协议的协商,因此无法进行签名。在此会话中稍后会有一个可靠的认证操作,在传递任何敏感信息之前,这不是一个安全问题。
签名消息
消息在位于write\_message
调用中签名。实际的签名过程是使用共享密钥加密消息的 CRC。因此,我们必须推迟签名,直到所有 CRC 都已计算完成。头部 CRC 最后计算,因此我们一计算完 CRC 就调用msg/Pipe.cc
中的sign\_message()
。
sign\_message()
是在auth/AuthSessionHandler.h
中定义的虚拟函数。因此,必须为每个支持的认证协议编写它的特定版本。目前,仅支持未知 UNKNOWN、无 NONE 和 CEPHX。所以有一个单独的sign\_message()
in
auth/unknown/AuthUnknownSessionHandler.h
, auth/none/AuthNoneSessionHandler.h
和auth/cephx/CephxSessionHandler.cc
版本。未知 UNKNOWN 和无 NONE 版本简单地返回 0,表示成功。
CEPHX 版本更广泛。它位于auth/cephx/CephxSessionHandler.cc
中。首先做的是确定处理签名的运行时选项(见上文)是否打开。如果没有,Cephx 版本的sign\_message()
简单地返回成功,而实际上没有计算签名或将其插入消息。
如果运行时选项已启用,sign\_message()
将消息的所有 CRC(一个来自头部和三个来自尾部)复制到缓冲区中。它调用encode\_encrypt()
在缓冲区上,使用从管道的session\_security
结构中获得的密钥。加密结果的 64 位被放入消息尾部的签名字段,并设置一个尾部标志以指示消息已被签名。(此标志是一个合理性检查。它不被视为消息已被签名的确凿证据。接收端存在session\_security
结构,无论此标志的值如何,都需要签名。)如果一切顺利,sign\_message()
返回 0。如果在任何环节出现问题并且没有计算签名,它返回SESSION\_SIGNATURE\_FAILURE
.
检查签名
签名由一个称为check\_message\_signature()
的例程检查。这也是一个虚拟函数,在auth/AuthSessionHandler.h
中定义。因此,再次为支持的认证协议(如未知 UNKNOWN、无 NONE 和 Cephx)有特定版本。再次,未知 UNKNOWN 和无 NONE 版本分别存储在auth/unknown/AuthUnknownSessionHandler.h
和auth/none/AuthNoneSessionHandler.h
中,并且它们简单地返回 0,表示成功。
CEPHX 版本的check\_message\_signature()
执行真实的签名检查。此例程(存储在auth/cephx/CephxSessionHandler.cc
中)如果运行时选项已禁用签名,则成功退出。否则,它从头部和尾部获取 CRC,加密结果,并将其与存储在尾部中的签名进行比较。由于一个早先的例程已经检查了 CRC 实际上与消息的内容匹配,因此没有必要在消息的原始数据上重新计算 CRC。加密是使用与发送端相同的encode\_encrypt()
例程执行的,使用存储在本地session\_security
数据结构中的密钥。
如果一切检查合格,Cephx 例程返回 0,表示成功。如果有问题,例程返回SESSION\_SIGNATURE\_FAILURE
.
添加新的会话认证方法
仅为了会话认证(而不是 Cephx 协议目前执行的客户端和服务器的基本认证),除了添加新协议之外,该协议必须有一个sign\_message()
例程和一个check\_message\_signature
例程。这些例程将以消息指针作为参数,并在成功时返回 0。用于签名和检查的流程将针对新方法特定,但可能有一个session\_security
结构附加到管道中,其中包含一个加密密钥。该结构将是AuthSessionHandler
(位于auth/AuthSessionHandler.h
中)或从中派生的结构。
为会话添加加密
现有的代码部分允许会话对其数据包进行加密,但并不完全。添加加密的一部分类似于添加新的认证方法。但还需要在write\_message()
和read\_message()
中添加对加密和解密例程的调用。这些调用可能靠近当前进行认证的调用位置。您应该考虑是否要使用更通用的东西来替换现有的调用,该通用东西执行所选会话安全形式所需的内容,而不是明确说明sign
或encrypt
.
会话安全统计
现有的 Cephx 认证代码对已签名的消息数量、已检查的消息签名数量以及成功和失败的检查数量进行统计。它准备对加密和解密保持类似的统计。这些统计可以通过调用printAuthSessionHandlerStats
in auth/AuthSessionHandler.cc
.
访问。如果添加了新的认证或加密方法,它们应该包括保持这些统计的代码。
由 Ceph 基金会带给您
Ceph 文档是一个社区资源,由非盈利的 Ceph 基金会资助和托管Ceph Foundation. 如果您想支持这一点和我们的其他工作,请考虑加入现在加入.