3.1. Generating an Outgoing SNMP Message (生成出站 SNMP 消息)
3.1. Generating an Outgoing SNMP Message (生成出站 SNMP 消息)
本节描述 SNMP 引擎在代表用户使用特定 securityLevel 生成包含管理操作 (如请求、响应、通知或报告) 的消息时所遵循的过程。
步骤 1: 确定用户信息 (Determine User Information)
1a) 响应或报告消息 (Response or Report Message)
如果传递了任何 securityStateReference (响应或报告消息), 则从 cachedSecurityData 中提取有关用户的信息。现在可以丢弃 cachedSecurityData。
- securityEngineID 设置为本地 snmpEngineID
- securityLevel 设置为调用模块指定的值
1b) 请求或通知消息 (Request or Notification Message)
否则, 根据 securityName, 从本地配置数据存储 (LCD, usmUserTable) 中提取有关目标 snmpEngineID (由 securityEngineID 指定) 处的用户的信息。
如果 LCD 中没有该用户的信息, 则向调用模块返回错误指示 (unknownSecurityName)。
步骤 2: 检查隐私支持 (Check Privacy Support)
如果 securityLevel 指定消息要受到保护免受泄露, 但用户不同时支持认证和隐私协议, 则无法发送消息。
向调用模块返回错误指示 (unsupportedSecurityLevel)。
注意: 隐私 (加密) 需要认证。不允许 noAuth + privacy 的组合。
步骤 3: 检查认证支持 (Check Authentication Support)
如果 securityLevel 指定消息要进行认证, 但用户不支持认证协议, 则无法发送消息。
向调用模块返回错误指示 (unsupportedSecurityLevel)。
步骤 4: 加密消息 (如果需要) (Encrypt the Message)
4a) 使用隐私 (authPriv)
如果 securityLevel 指定消息要受到保护免受泄露, 则根据用户的隐私协议加密表示序列化 scopedPDU 的字节序列。
为此, 根据抽象原语调用实现用户隐私协议的隐私模块:
statusInformation = -- 成功或失败
encryptData(
IN encryptKey -- 用户的本地化 privKey
IN dataToEncrypt -- 序列化的 scopedPDU
OUT encryptedData -- 序列化的 encryptedPDU
OUT privParameters -- 序列化的隐私参数
)
参数 (Parameters):
-
statusInformation: 指示加密过程是否成功
-
encryptKey: 用户的本地化私有 privKey 是可以由加密算法使用的秘密密钥
-
dataToEncrypt: 序列化的 scopedPDU 是要加密的数据
-
encryptedData: encryptedPDU 表示加密的 scopedPDU, 编码为 OCTET STRING
-
privParameters: 隐私参数, 编码为 OCTET STRING
错误处理 (Error Handling):
如果隐私模块返回失败, 则无法发送消息, 并向调用模块返回错误指示 (encryptionError)。
如果隐私模块返回成功, 则:
- 返回的 privParameters 放入 securityParameters 的 msgPrivacyParameters 字段
- encryptedPDU 作为正在准备的消息的有效负载
4b) 不使用隐私 (noAuthNoPriv 或 authNoPriv)
如果 securityLevel 指定消息不受保护免受泄露, 则:
- 将零长度 OCTET STRING 编码到 securityParameters 的 msgPrivacyParameters 字段
- 明文 scopedPDU 作为正在准备的消息的有效负载
步骤 5: 设置 msgAuthoritativeEngineID
将 securityEngineID 编码为 OCTET STRING 到 securityParameters 的 msgAuthoritativeEngineID 字段。
注意: 对于请求消息, 空的 (零长度) securityEngineID 是可以的, 因为这将导致远程 (权威) SNMP 引擎返回报告 PDU, 该报告 PDU 的 securityParameters 中的 msgAuthoritativeEngineID 中包含正确的 securityEngineID。这是发现机制的一部分。
步骤 6: 设置 snmpEngineBoots 和 snmpEngineTime
6a) 已认证消息 (Authenticated Message)
如果 securityLevel 指定消息要进行认证, 则使用 LCD 中与 securityEngineID 对应的当前 snmpEngineBoots 和 snmpEngineTime 值。
6b) 响应或报告消息 (未认证) (Response or Report Message - unauthenticated)
否则, 如果这是响应或报告消息, 则使用 LCD 中与本地 snmpEngineID 对应的当前 snmpEngineBoots 和 snmpEngineTime 值。
6c) 其他未认证消息 (Other Unauthenticated Messages)
否则 (这是未认证的请求或通知), snmpEngineBoots 和 snmpEngineTime 都设置为零。
步骤 7: 编码时间值 (Encode Time Values)
将 msgAuthoritativeEngineBoots 和 msgAuthoritativeEngineTime 的值设置为步骤 6 中确定的值, 并编码为 INTEGER 值到 securityParameters 中。
步骤 8: 设置 msgUserName
将 msgUserName 字段设置为 securityName, 并编码为 OCTET STRING 到 securityParameters 中。
步骤 9: 认证消息 (如果需要) (Authenticate the Message)
9a) 使用认证 (authNoPriv 或 authPriv)
如果 securityLevel 指定消息要进行认证, 则根据用户的认证协议对消息进行认证。
将 msgAuthenticationParameters 字段设置为根据认证协议规则序列化的:
authenticationInformation =
authenticationAlgorithm(
IN authKey -- 用户的本地化 authKey
IN wholeMsg -- 未认证的消息
)
过程 (Process):
-
msgAuthenticationParameters 字段临时填充由认证协议确定的值 (对于 HMAC-MD5-96 和 HMAC-SHA-96 通常为 12 个零字节)
-
对整个序列化消息 (wholeMsg) 运行认证算法
-
认证算法的输出 (MAC/摘要) 替换 msgAuthenticationParameters 中的临时值
参数 (Parameters):
-
authKey: 用户的本地化私有 authKey 是认证算法使用的秘密密钥
-
wholeMsg: 未认证的消息 (msgAuthenticationParameters 临时设置为零)
-
authenticationInformation: 计算的认证摘要/MAC
将计算的认证摘要放入 msgAuthenticationParameters 字段。
9b) 不使用认证 (noAuthNoPriv)
如果 securityLevel 指定消息不进行认证, 则将零长度 OCTET STRING 编码到 msgAuthenticationParameters 字段。
步骤 10: 完成并返回 (Finalize and Return)
将完成的 wholeMsg 与指示成功的 statusInformation 一起返回给调用模块。
Message Generation Flow Summary (消息生成流程摘要)
1. 查找用户信息 (从缓存或 LCD)
2. 验证安全级别支持
3. 检查认证支持
4. 加密 scopedPDU (如果是 authPriv)
└─> 设置 msgPrivacyParameters
5. 设置 msgAuthoritativeEngineID
6. 确定时间值 (boots/time)
7. 编码时间值
8. 设置 msgUserName
9. 认证消息 (如果是 authNoPriv 或 authPriv)
└─> 计算 MAC/摘要
└─> 设置 msgAuthenticationParameters
10. 返回完整的 wholeMsg
Special Cases (特殊情况)
Discovery Messages (发现消息)
对于发现消息:
- securityEngineID 为空 (零长度)
- securityLevel 为 noAuthNoPriv
- msgAuthoritativeEngineID 为空
- msgAuthoritativeEngineBoots 和 msgAuthoritativeEngineTime 为零
- msgUserName 为空
- msgAuthenticationParameters 为空
- msgPrivacyParameters 为空
Notification Messages (通知消息)
对于通知消息 (Trap, Inform):
- 通知发起者 (notification originator) 是权威引擎
- securityEngineID 是本地 snmpEngineID
- 使用本地 snmpEngineBoots 和 snmpEngineTime 值
Error Conditions (错误条件)
可能返回以下错误指示:
| 错误 (Error) | 条件 (Condition) |
|---|---|
| unknownSecurityName | 在 LCD 中未找到用户 |
| unsupportedSecurityLevel | 用户缺少所需的认证或隐私协议 |
| encryptionError | 隐私模块未能加密数据 |
Implementation Notes (实现注意事项)
-
缓存的安全数据 (Cached Security Data): 对于响应和报告消息, 从处理原始请求消息期间保存的缓存数据中检索安全信息
-
时间同步 (Time Synchronization): 已认证消息使用 LCD 中目标权威引擎的时间值。这些值必须保持同步 (参见第 4 节关于发现)
-
密钥使用 (Key Usage): 必须使用特定 securityEngineID 的本地化 authKey 和 privKey
-
消息大小 (Message Size): 实现必须确保生成的消息不超过与远程引擎协商的 maxMessageSize