GSSAPI:安全上下文循环
GSSAPI: The Security Context Loop
Oracle GSSAPI Java 示例和各种 SPNEGO / GSSAPI IETF RFC 表明 GSS 发起方(客户端)和接受方(服务器)都应该有一个循环来建立安全上下文,并且客户端在建立安全上下文之前,可能需要使用 GSS 令牌进行多次传递。
Oracle GSSAPI 示例:
https://docs.oracle.com/javase/8/docs/technotes/guides/security/jgss/tutorials/BasicClientServer.html
通用安全服务 (GSS) 协商循环的结构:
https://www.rfc-editor.org/rfc/rfc7546
Microsoft 中基于 SPNEGO 的 Kerberos 和 NTLM HTTP 身份验证 Windows:
https://www.rfc-editor.org/rfc/rfc4559
例如 RFC4559 给出了这个例子:
通过 1: 失败,因为请求没有令牌:
C: 获取 dir/index.html
S: HTTP/1.1 401 未经授权
S:WWW-验证:协商
通过 2: 失败,但请求有令牌
C: 获取 dir/index.html
C:授权:协商a87421000492aa874209af8bc028
S: HTTP/1.1 401 未经授权
S: WWW-Authenticate: 协商 749efa7b23409c20b92356
第 3 关: 成功
C: 获取 dir/index.html
C:授权:协商89a8742aa8729a8b028
S: HTTP/1.1 200 成功
S: WWW-Authenticate: 协商 ade0234568a4209af8bc0280289eca
这里建立了安全上下文,因此请求在第三次通过时进行了身份验证。即在从客户端 (C) 到服务器 (S) 的第二次传递中带有令牌。
问题 1:
为什么在成功建立安全上下文之前需要使用令牌从发起者到接受者进行多次传递?
为什么上面的 pass 2 可能会失败,但 pass 3 会成功?
在这两次传递之间,发起者或接受者有什么变化吗?
问题 2:
我的直觉是发起者和接受者循环都应该有防止无限循环的保护。
例如,如果 x 次尝试未建立上下文,发起者可能会中止。
是否有任何关于可以合理预期建立安全上下文的通行证数量的经验法则/指标?
例如如果到第 5 遍还没有建立安全上下文 --> 中止。
问题 3:
在 Oracle GSSAPI 示例中,客户端和服务器通过套接字进行通信。
服务器构建一个专用于单个客户端的 GSSContext 对象,一直保留到服务器关闭,因此可用于多次传递以建立安全上下文。
但是这对于具有多个客户端的 Http RESTful WebServer 是如何工作的呢?
我的假设是:
a) 建立安全上下文的请求的每次传递都应针对同一个 GSSContext 对象(而不是针对新的 GSSContext 实例)。
b) Http 服务器应该为每个新的客户端请求建立一个新的 GSSContext 实例。
(即 GSSContext 对象不应在多个客户端/请求之间共享/重用)。
如果我的假设是正确的,服务器必须区分:
i) 针对尚未建立安全上下文的现有请求的后续传递。 --> 应使用现有的 GSSContext 对象和循环。
ii) 全新请求的第一次传递(来自相同或不同的客户端)。 --> 应使用新的 GSSContext 对象和循环。
使用 Negotiate
作为示例协议,考虑它的运作方式很有用。
- 服务器向客户端表明它可以支持协商。
- 客户端同意并推断出服务器可能支持的内容。
- 客户端根据它真正认为服务器支持的内容(例如 Kerberos)创建令牌,然后创建其他可能的令牌类型列表(例如 NTLM)。
- 客户端将令牌和列表都发送到服务器。
- 服务器要么接受初始令牌,要么决定从列表中选择其他内容。
- 服务器向客户端表明它需要其他东西。
- 然后客户端发送另一个首选类型的令牌。
- 服务器接受或拒绝并适当地响应客户端。
这最多需要 3 次往返,一次后可能会失败或完成。其他协议可能会选择为所欲为。
您可能想要跟踪往返次数,并在任意高的次数后将其终止。所需资源不是那么多,但在负载下它会耗尽系统。
Oracle GSSAPI Java 示例和各种 SPNEGO / GSSAPI IETF RFC 表明 GSS 发起方(客户端)和接受方(服务器)都应该有一个循环来建立安全上下文,并且客户端在建立安全上下文之前,可能需要使用 GSS 令牌进行多次传递。
Oracle GSSAPI 示例: https://docs.oracle.com/javase/8/docs/technotes/guides/security/jgss/tutorials/BasicClientServer.html
通用安全服务 (GSS) 协商循环的结构: https://www.rfc-editor.org/rfc/rfc7546
Microsoft 中基于 SPNEGO 的 Kerberos 和 NTLM HTTP 身份验证 Windows: https://www.rfc-editor.org/rfc/rfc4559
例如 RFC4559 给出了这个例子:
通过 1: 失败,因为请求没有令牌:
C: 获取 dir/index.html
S: HTTP/1.1 401 未经授权
S:WWW-验证:协商
通过 2: 失败,但请求有令牌
C: 获取 dir/index.html
C:授权:协商a87421000492aa874209af8bc028
S: HTTP/1.1 401 未经授权
S: WWW-Authenticate: 协商 749efa7b23409c20b92356
第 3 关: 成功
C: 获取 dir/index.html
C:授权:协商89a8742aa8729a8b028
S: HTTP/1.1 200 成功
S: WWW-Authenticate: 协商 ade0234568a4209af8bc0280289eca
这里建立了安全上下文,因此请求在第三次通过时进行了身份验证。即在从客户端 (C) 到服务器 (S) 的第二次传递中带有令牌。
问题 1: 为什么在成功建立安全上下文之前需要使用令牌从发起者到接受者进行多次传递? 为什么上面的 pass 2 可能会失败,但 pass 3 会成功? 在这两次传递之间,发起者或接受者有什么变化吗?
问题 2: 我的直觉是发起者和接受者循环都应该有防止无限循环的保护。 例如,如果 x 次尝试未建立上下文,发起者可能会中止。 是否有任何关于可以合理预期建立安全上下文的通行证数量的经验法则/指标? 例如如果到第 5 遍还没有建立安全上下文 --> 中止。
问题 3: 在 Oracle GSSAPI 示例中,客户端和服务器通过套接字进行通信。 服务器构建一个专用于单个客户端的 GSSContext 对象,一直保留到服务器关闭,因此可用于多次传递以建立安全上下文。
但是这对于具有多个客户端的 Http RESTful WebServer 是如何工作的呢? 我的假设是:
a) 建立安全上下文的请求的每次传递都应针对同一个 GSSContext 对象(而不是针对新的 GSSContext 实例)。
b) Http 服务器应该为每个新的客户端请求建立一个新的 GSSContext 实例。 (即 GSSContext 对象不应在多个客户端/请求之间共享/重用)。
如果我的假设是正确的,服务器必须区分:
i) 针对尚未建立安全上下文的现有请求的后续传递。 --> 应使用现有的 GSSContext 对象和循环。
ii) 全新请求的第一次传递(来自相同或不同的客户端)。 --> 应使用新的 GSSContext 对象和循环。
使用 Negotiate
作为示例协议,考虑它的运作方式很有用。
- 服务器向客户端表明它可以支持协商。
- 客户端同意并推断出服务器可能支持的内容。
- 客户端根据它真正认为服务器支持的内容(例如 Kerberos)创建令牌,然后创建其他可能的令牌类型列表(例如 NTLM)。
- 客户端将令牌和列表都发送到服务器。
- 服务器要么接受初始令牌,要么决定从列表中选择其他内容。
- 服务器向客户端表明它需要其他东西。
- 然后客户端发送另一个首选类型的令牌。
- 服务器接受或拒绝并适当地响应客户端。
这最多需要 3 次往返,一次后可能会失败或完成。其他协议可能会选择为所欲为。
您可能想要跟踪往返次数,并在任意高的次数后将其终止。所需资源不是那么多,但在负载下它会耗尽系统。