2. 服务器和客户端行为
2.1. 响应头字段语法
Expect-CT 响应头字段是本规范定义的新字段. 服务器使用它指示 UA 应评估到发出该头字段的主机的连接是否符合 CT 要求 (第 2.4 节).
图 1 使用 [RFC5234] 中定义的语法以及 [RFC9110] 第 5 节中定义的规则, 描述该头字段的语法 (Augmented Backus-Naur Form). "#" ABNF 扩展在 [RFC9110] 第 5.6.1 节中规定.
Expect-CT = 1#expect-ct-directive
expect-ct-directive = directive-name [ "=" directive-value ]
directive-name = token
directive-value = token / quoted-string
图 1: Expect-CT 头字段的语法
本规范定义的指令如下所述. 指令的总体要求为:
-
指令出现的顺序没有意义.
-
给定指令在给定头字段中 MUST NOT 出现多于一次. 指令可以是可选的或必需的, 由其定义规定.
-
指令名称不区分大小写.
-
对于包含不符合本规范定义语法的指令或其他头字段值数据的任何头字段, UA MUST 忽略. 特别是, UA MUST NOT 尝试修复格式错误的头字段.
-
如果头字段包含 UA 不识别的任何指令, UA MUST 忽略这些指令.
-
如果 Expect-CT 头字段在其他方面满足上述要求 (1 到 5), 且 Expect-CT 未因本地策略原因被禁用 (见第 2.4.1 节), UA MUST 处理其识别的指令.
2.1.1. report-uri 指令
OPTIONAL 的 report-uri 指令指示 UA SHOULD 将 Expect-CT 失败报告到的 URI (第 2.4 节). UA 按第 3 节所述向给定 URI POST 报告.
report-uri 指令 REQUIRED 带有指令值, 其语法在图 2 中定义.
report-uri-value = (DQUOTE absolute-URI DQUOTE) / absolute-URI
图 2: report-uri 指令值的语法
如果 'report-uri-value' 包含 'token' 中不允许的任何字符, 则 MUST 加引号.
absolute-URI 在 [RFC3986] 第 4.3 节中定义.
UA MUST 忽略任何未使用 HTTPS scheme 的 report-uri. 当 report-uri 中的主机是 Known Expect-CT Host 时, UA MUST 检查 Expect-CT 合规性. 类似地, 如果 report-uri 中的主机是 Known HSTS Host, UA MUST 应用 HSTS [RFC6797].
UA SHOULD 尽最大努力将 Expect-CT 失败报告到 report-uri, 但在异常条件下可能无法报告. 例如, 如果连接到 report-uri 本身会导致 Expect-CT 失败或其他证书验证失败, UA MUST 取消该连接. 类似地, 如果 Expect-CT Host A 设置的 report-uri 指向 Expect-CT Host B, B 又设置的 report-uri 指向 A, 且两个主机都不符合 UA 的 CT Policy, UA SHOULD 检测并打破该循环, 不向这些主机发送关于这些主机的报告.
注意, report-uri 不一定必须与被报告的主机位于同一 Internet 域或 Web origin. 实际上鼓励主机使用独立主机作为 report-uri, 以便 Expect-CT Host 上的 CT 失败不会阻止报告发送.
UA SHOULD 限制发送报告的速率. 例如, 在同一 Web 浏览会话中, 不必向同一 report-uri 多次发送相同报告.
2.1.2. enforce 指令
OPTIONAL 的 enforce 指令是不带值的指令. 如果存在 (即被 "asserted"), 它向 UA 表明应强制执行 CT Policy 合规性 (而不是仅报告), 且 UA 应拒绝未来违反其 CT Policy 的连接. 当 enforce 指令和 report-uri 指令 (如图 2 所定义) 同时存在时, 该配置称为 "enforce-and-report" 配置, 表示 UA 既应强制执行 CT Policy 合规性, 也应报告违规.
2.1.3. max-age 指令
max-age 指令指定从接收 Expect-CT 头字段开始的秒数, 在此期间 UA SHOULD 将接收该消息的来源主机视为 Known Expect-CT Host.
如果响应包含 Expect-CT 头字段, 则该响应 MUST 包含一个带有 max-age 指令的 Expect-CT 头字段. (max-age 指令不必出现在响应中的每个 Expect-CT 头字段内.) max-age 指令 REQUIRED 带有指令值, 其语法 (如有必要, 在 quoted-string 反转义后) 在图 3 中定义.
max-age-value = delta-seconds
delta-seconds = 1*DIGIT
图 3: max-age 指令值的语法
delta-seconds 按 [RFC9111] 第 1.3 节中的定义使用.
2.1.4. 示例
以下三个示例展示了有效的 Expect-CT 响应头字段 (其中第二个示例将指令拆分到两个字段实例中):
Expect-CT: max-age=86400, enforce
Expect-CT: max-age=86400,enforce
Expect-CT: report-uri="https://foo.example/report"
Expect-CT: max-age=86400,report-uri="https://foo.example/report"
图 4: 有效 Expect-CT 响应头字段示例
2.2. 主机处理模型
本节描述 Expect-CT Host 实现的处理模型. 该模型包含 2 个部分: (1) 对通过安全传输 (例如经过认证的非匿名 TLS) 接收的 HTTP 请求消息的处理规则. (2) 对通过非安全传输 (例如 TCP) 接收的 HTTP 请求消息的处理规则.
2.2.1. 安全传输上的 HTTP 请求类型
Expect-CT Host 在其响应中包含 Expect-CT 头字段. 该头字段 MUST 满足第 2.1 节指定的语法.
在给定 UA 的上下文中, 将给定主机确立为 Expect-CT Host 的方式如下:
-
通过运行在安全传输上的 HTTP 协议, 按本规范向 UA 正确返回有效的 Expect-CT 头字段.
-
通过其他机制, 例如客户端侧预加载的 Expect-CT Host 列表.
2.2.2. HTTP 请求类型
Expect-CT Host SHOULD NOT 在通过非安全传输传送的 HTTP 响应中包含 Expect-CT 头字段.
2.3. 用户代理处理模型
UA 处理模型依赖于解析域名. 注意, 国际化域名 SHALL 由 UA 按 [RFC6797] 第 10 节中的方案规范化.
UA 存储 Known Expect-CT Hosts 及其关联的 Expect-CT 指令. 这些数据统称为主机的 "Expect-CT metadata".
2.3.1. 缺失或格式错误的 Expect-CT 头字段
如果 HTTP 响应不包含符合第 2.1 节所指定语法的 Expect-CT 头字段, 则 UA MUST NOT 更新任何 Expect-CT metadata.
2.3.2. Expect-CT 头字段处理
如果 UA 通过安全传输接收到包含 Expect-CT 头字段的 HTTP 响应, 且该头字段符合第 2.1 节指定的语法, 则 UA MUST 评估接收该头字段的连接是否符合 UA 的 CT Policy, 然后按如下方式处理 Expect-CT 头字段. 对于通过非安全传输传送的 HTTP 响应中接收的任何 Expect-CT 头字段, UA MUST 忽略.
如果连接不符合 UA 的 CT Policy (即连接不是 CT qualified), 则 UA MUST NOT 更新任何 Expect-CT metadata. 如果头字段包含 report-uri 指令, UA SHOULD 向指定的 report-uri 发送报告 (第 2.3.3 节).
如果连接符合 UA 的 CT Policy (即连接是 CT qualified), 则 UA MUST 执行以下二者之一:
-
如果尚未如此记录该主机, 则将其记录为 Known Expect-CT Host (见第 2.3.2.1 节), 或
-
如果 enforce, max-age 或 report-uri 头字段值指令传达的信息不同于 UA 已维护的信息, 则更新 UA 为该 Known Expect-CT Host 缓存的信息. 如果 max-age 指令值为 0, 且该主机先前已被记录为 Known Expect-CT Host, UA MUST 移除其缓存的 Expect-CT 信息. 如果该主机尚未被记录, UA MUST NOT 将此主机记录为 Known Expect-CT Host.
如果 UA 在 CT 合规连接上接收到 Expect-CT 头字段, 但该连接使用 [RFC6962] 或 [RFC9162] 以外的 Certificate Transparency 版本, 则 UA MUST 忽略该 Expect-CT 头字段并清除与该主机关联的任何 Expect-CT metadata.
2.3.2.1. 记录 Expect-CT
在无错误的 TLS 连接上收到 Expect-CT 响应头字段后 (包括 [RFC5280] 所述的 X.509 证书链验证以及本文档第 2.4 节所述的验证), UA MUST 将该主机记录为 Known Expect-CT Host, 并在非易失性存储中保存该主机的域名及其关联的 Expect-CT 指令.
为了将主机记录为 Known Expect-CT Host, UA MUST 使用最近接收到的有效 Expect-CT 头字段给出的 metadata, 在其 Known Expect-CT Host 缓存中设置该主机的 Expect-CT metadata (如第 2.3.2.2 节所规定).
为实现向前兼容, UA MUST 忽略任何无法识别的 Expect-CT 头字段指令, 同时仍处理其能够识别的指令. 第 2.1 节规定了 enforce, max-age 和 report-uri 指令, 但未来的规范和实现可能会使用其他指令.
2.3.2.2. 存储模型
如果从 Request-URI (主机所响应的消息的 Request-URI) 中匹配 host 产生式的子串, 按 [RFC6797] 第 8.2 节中 Congruent Match 的匹配过程, 与现有 Known Expect-CT Host 的域名不完全匹配, 则 UA MUST 将该主机加入 Known Expect-CT Host 缓存. UA 缓存:
-
Expect-CT Host 的域名.
-
enforce 指令是否存在.
-
Effective Expiration Date, 即 Effective Expect-CT Date 加上 max-age 指令的值. 或者, UA MAY 缓存足够的信息以计算 Effective Expiration Date. Effective Expiration Date 从 UA 观察到 Expect-CT 头字段的时间开始计算, 与响应生成时间无关.
-
report-uri 指令的值, 如果存在.
如果 Expect-CT 头字段中存在来自可选或未来 Expect-CT 头指令的任何其他 metadata, 且 UA 能理解它们, 则 UA MAY 也记录这些 metadata.
UA MAY 对 max-age 的值设置上限, 使那些记录了错误 Expect-CT Host 的 UA (无论是意外还是攻击导致) 有机会随时间恢复. 如果服务器设置的 max-age 大于 UA 的上限, UA 可以表现得好像服务器将 max-age 设置为 UA 的上限. 例如, 如果 UA 将 max-age 限制为 5,184,000 秒 (60 天), 而 Expect-CT Host 在其 Expect-CT 头字段中设置 90 天的 max-age 指令, UA 可以表现得好像 max-age 实际为 60 天. (实现这种行为的一种方式是 UA 直接存储 60 天的值, 而不是 Expect-CT Host 提供的 90 天值.)
2.3.3. 报告
如果 UA 通过安全传输接收到的 HTTP 响应包含带 report-uri 指令的 Expect-CT 头字段, 且该连接不符合 UA 的 CT Policy (即连接不是 CT qualified), 并且 UA 尚未为此连接发送 Expect-CT 报告, 则 UA SHOULD 按第 3 节所规定向指定的 report-uri 发送报告.
2.4. 评估 Expect-CT 连接的 CT 合规性
当 UA 建立 TLS 连接时, UA 根据其 Known Expect-CT Host 缓存确定该主机是否为 Known Expect-CT Host. 如果 Effective Expiration Date 指向过去的日期, 则 Expect-CT Host 为 "expired". UA MUST 忽略其缓存中任何已过期的 Expect-CT Host, 且不得将此类主机视为 Known Expect-CT Host.
当 UA 使用 TLS 连接到 Known Expect-CT Host 时, 如果 TLS 连接没有错误, UA 将应用额外的正确性检查: 是否符合 CT Policy. 每当连接到 Known Expect-CT Host 时, UA 都应评估是否符合其 CT Policy. 但是, 出于本地策略原因 (见第 2.4.1 节), 或者在其他检查导致 UA 在评估 CT 合规性之前终止连接的情况下, 可以跳过该检查. 例如, Public Key Pinning 失败 [RFC7469] 可能导致 UA 在检查 CT 合规性之前终止连接. 类似地, 如果 UA 因 Expect-CT 失败而终止连接, 这可能导致 UA 跳过后续正确性检查. 当 CT 合规性检查被跳过或绕过时, 不会发送 Expect-CT 报告 (第 3 节).
当评估 Known Expect-CT Host 的 CT 合规性时, UA MUST 在建立 TLS 会话时评估合规性, 且必须在通过 TLS 信道开始 HTTP 会话之前完成.
如果到 Known Expect-CT Host 的连接违反 UA 的 CT Policy (即连接不是 CT qualified), 且该 Known Expect-CT Host 的 Expect-CT metadata 指示 enforce 配置, 则 UA MUST 将 CT 合规性失败视为错误. UA MAY 允许用户绕过该错误, 除非由于其他生效策略 (例如 [RFC6797] 第 12.1 节所述的 HSTS), 连接错误不应提供用户补救路径.
如果到 Known Expect-CT Host 的连接违反 UA 的 CT Policy, 且该 Known Expect-CT Host 的 Expect-CT metadata 包含 report-uri, 则 UA SHOULD 向该 report-uri 发送 Expect-CT 报告 (第 3 节).
2.4.1. 跳过 CT 合规性检查
UA 可以按照本地策略对某些主机跳过 CT 合规性检查. 例如, 对于其已验证证书链终止于用户定义的信任锚, 而不是 UA (或底层平台) 内置的信任锚的主机, UA MAY 禁用 CT 合规性检查.
如果 UA 不评估 CT 合规性, 例如因为用户选择禁用它, 或因为提供的证书链链向用户定义的信任锚, 则 UA SHOULD NOT 发送 Expect-CT 报告.