跳到主要内容

3.2. Processing an Incoming SNMP Message (处理传入的 SNMP 消息)

3.2. Processing an Incoming SNMP Message (处理传入的 SNMP 消息)

本节描述 SNMP 引擎在代表用户接收包含管理操作的消息时所遵循的过程, 该消息具有特定的 securityLevel。

General Notes (一般说明)

为了简化过程要素, 并不总是明确指定状态信息的释放。一般规则是, 如果在消息被丢弃时状态信息可用, 则也应释放状态信息。

此外, 错误指示可以返回:

  • 递增计数器的 OID 和值
  • 可选的 securityLevel 值
  • 计数器的 contextEngineID 或 contextName 值
  • 如果在检测到错误的点有任何此类信息可用, 则返回 securityStateReference 数据

步骤 1: 解析 securityParameters

如果接收到的 securityParameters 不是根据第 2.4 节中定义的 UsmSecurityParameters 格式化的 OCTET STRING 的序列化 (根据 RFC 3417 的约定), 则:

  • 递增 snmpInASNParseErrs 计数器 (RFC 3418)
  • 向调用模块返回错误指示 (parseError)

注意: 我们返回时不带递增计数器的 OID 和值, 因为在这种情况下没有足够的信息来生成报告 PDU。

步骤 2: 提取安全参数 (Extract Security Parameters)

从 securityParameters 中提取安全参数字段的值。

  • 要返回给调用者的 securityEngineID 是 msgAuthoritativeEngineID 字段的值
  • 准备 cachedSecurityData 并准备 securityStateReference 来引用此数据

要缓存的值 (Values to be cached):

  • msgUserName
  • msgAuthoritativeEngineID
  • msgAuthoritativeEngineBoots
  • msgAuthoritativeEngineTime
  • msgAuthenticationParameters
  • msgPrivacyParameters

步骤 3: 检查 msgAuthoritativeEngineID

如果 securityParameters 中的 msgAuthoritativeEngineID 字段的值未知, 则:

选项 a) 发现模式 (非权威引擎) (Discovery Mode)

执行发现的非权威 SNMP 引擎可以选择在其本地配置数据存储 (LCD) 中创建新条目并继续处理。

选项 b) 返回错误 (Return Error)

递增 usmStatsUnknownEngineIDs 计数器, 并向调用模块返回错误指示 (unknownEngineID) 以及递增计数器的 OID 和值。

注意: 如果接收到零长度或其他非法大小的 msgAuthoritativeEngineID, 应选择选项 b) 以促进 engineID 发现。否则, a) 和 b) 之间的选择是实现问题。

步骤 4: 查找用户信息 (Lookup User Information)

从本地配置数据存储 (LCD, usmUserTable) 中提取有关 msgUserName 和 msgAuthoritativeEngineID 字段值的信息。

如果没有该用户的可用信息, 则:

  • 递增 usmStatsUnknownUserNames 计数器
  • 向调用模块返回错误指示 (unknownSecurityName) 以及递增计数器的 OID 和值

步骤 5: 检查安全级别支持 (Check Security Level Support)

如果有关用户的信息指示它不支持调用者请求的 securityLevel, 则:

  • 递增 usmStatsUnsupportedSecLevels 计数器
  • 向调用模块返回错误指示 (unsupportedSecurityLevel) 以及递增计数器的 OID 和值

步骤 6: 认证消息 (如果需要) (Authenticate Message)

如果 securityLevel 指定消息要进行认证, 则根据用户的认证协议对消息进行认证。

为此, 根据抽象服务原语调用实现用户认证协议的认证模块:

statusInformation =          -- 成功或失败
authenticateIncomingMsg(
IN authKey -- 用户的本地化 authKey
IN authParameters -- 从网络接收的
IN wholeMsg -- 从网络接收的
OUT authenticatedWholeMsg -- 已检查认证
)

参数 (Parameters):

  • statusInformation: 指示认证是否成功

  • authKey: 用户的本地化私有 authKey 是认证算法可以使用的秘密密钥

  • authParameters: 消息中接收到的 msgAuthenticationParameters

  • wholeMsg: 要认证的完整序列化消息

  • authenticatedWholeMsg: 与给 authenticateIncomingMsg 服务的输入相同, 但在检查认证之后

错误处理 (Error Handling):

如果认证模块返回失败, 则无法信任消息, 因此:

  • 递增 usmStatsWrongDigests 计数器
  • 向调用模块返回错误指示 (authenticationFailure) 以及递增计数器的 OID 和值

如果认证模块返回成功, 则消息是真实的并且可以信任, 因此继续处理。

步骤 7: 检查时间窗口 (对于已认证消息) (Check Time Window)

如果 securityLevel 指示已认证消息, 则从本地配置数据存储中提取与 msgAuthoritativeEngineID 字段值对应的 snmpEngineBoots、snmpEngineTime 和 latestReceivedEngineTime 的本地值。

7a) 权威引擎 (msgAuthoritativeEngineID == 本地 snmpEngineID)

如果提取的 msgAuthoritativeEngineID 值与处理 SNMP 引擎的 snmpEngineID 值相同 (意味着这是权威 SNMP 引擎), 则如果以下任何条件为真, 则认为消息在时间窗口之外:

  1. snmpEngineBoots 的本地值为 2147483647 (达到最大值)

  2. msgAuthoritativeEngineBoots 字段的值与 snmpEngineBoots 的本地值不同

  3. msgAuthoritativeEngineTime 字段的值与 snmpEngineTime 的本地概念相差超过 +/- 150 秒

如果在时间窗口之外:

  • 递增 usmStatsNotInTimeWindows 计数器
  • 向调用模块返回错误指示 (notInTimeWindow) 以及 OID、递增计数器的值, 以及必须使用 securityLevel 为 authNoPriv 报告错误的指示

7b) 非权威引擎 (msgAuthoritativeEngineID != 本地 snmpEngineID)

如果提取的 msgAuthoritativeEngineID 值与处理 SNMP 引擎的 snmpEngineID 值不同 (意味着这不是权威 SNMP 引擎), 则:

7b.1) 更新时间信息 (如果更新) (Update Time Information)

如果以下至少一个条件为真:

  • msgAuthoritativeEngineBoots 字段的提取值大于 snmpEngineBoots 值的本地概念; 或

  • msgAuthoritativeEngineBoots 字段的提取值等于 snmpEngineBoots 值的本地概念, 并且 msgAuthoritativeEngineTime 字段的提取值大于 latestReceivedEngineTime 的值

那么更新与 msgAuthoritativeEngineID 字段的提取值对应的 LCD 条目, 通过设置:

  • snmpEngineBoots 值的本地概念为 msgAuthoritativeEngineBoots 字段的值
  • snmpEngineTime 值的本地概念为 msgAuthoritativeEngineTime 字段的值
  • latestReceivedEngineTime 为 msgAuthoritativeEngineTime 字段的值
7b.2) 检查时间窗口 (Check Time Window)

如果以下任何条件为真, 则认为消息在时间窗口之外:

  1. snmpEngineBoots 值的本地概念为 2147483647

  2. msgAuthoritativeEngineBoots 字段的值小于 snmpEngineBoots 值的本地概念

  3. msgAuthoritativeEngineBoots 字段的值等于 snmpEngineBoots 值的本地概念, 并且 msgAuthoritativeEngineTime 字段的值比 snmpEngineTime 值的本地概念少 150 秒以上

如果在时间窗口之外:

  • 递增 usmStatsNotInTimeWindows 计数器
  • 向调用模块返回错误指示 (notInTimeWindow) 以及递增计数器的 OID 和值

步骤 8: 解密消息 (如果需要) (Decrypt Message)

如果 securityLevel 指示消息受到保护免受泄露 (隐私), 则根据用户的隐私协议解密表示 encryptedPDU 的 OCTET STRING。

为此, 根据抽象服务原语调用实现用户隐私协议的隐私模块:

statusInformation =         -- 成功或失败
decryptData(
IN decryptKey -- 用户的本地化 privKey
IN privParameters -- 从网络接收的
IN encryptedData -- 接收到的 encryptedPDU
OUT decryptedData -- 解密的 scopedPDU
)

参数 (Parameters):

  • statusInformation: 指示解密过程是否成功

  • decryptKey: 用户的本地化私有 privKey 是解密算法使用的秘密密钥

  • privParameters: 消息中接收到的 msgPrivacyParameters

  • encryptedData: 消息中的 encryptedPDU

  • decryptedData: 解密的 scopedPDU

错误处理 (Error Handling):

如果隐私模块返回失败, 则无法处理消息, 因此:

  • 递增 usmStatsDecryptionErrors 计数器
  • 向调用模块返回错误指示 (decryptionError) 以及递增计数器的 OID 和值

如果隐私模块返回成功, 则解密的 scopedPDU 用于进一步处理。

步骤 9: 返回结果 (Return Results)

以下值返回给调用消息处理模块:

  • securityEngineID: msgAuthoritativeEngineID
  • securityName: msgUserName
  • scopedPDU: 解密的 scopedPDU (如果有隐私) 或明文 scopedPDU
  • maxSizeResponseScopedPDU: 根据消息大小约束计算
  • securityStateReference: 对缓存安全数据的引用

Processing Flow Summary (处理流程摘要)

1. 解析 securityParameters
2. 提取安全参数字段
3. 检查 msgAuthoritativeEngineID (未知 -> 错误或创建条目)
4. 在 LCD 中查找用户 (未知用户 -> 错误)
5. 检查安全级别支持 (不支持 -> 错误)
6. 认证消息 (如果 authNoPriv 或 authPriv)
└─> 验证 MAC/摘要 (错误 -> 错误)
7. 检查时间窗口 (如果已认证)
└─> 对于权威: 验证 boots 和 time
└─> 对于非权威: 如果更新则更新时间信息, 然后验证
└─> 在窗口外 -> 错误
8. 解密消息 (如果 authPriv)
└─> 解密 encryptedPDU (失败 -> 错误)
9. 返回 securityEngineID, securityName, scopedPDU 等

Error Conditions Summary (错误条件摘要)

错误 (Error)计数器 (Counter)条件 (Condition)
parseErrorsnmpInASNParseErrs无效的 securityParameters 格式
unknownEngineIDusmStatsUnknownEngineIDs未知的 msgAuthoritativeEngineID
unknownSecurityNameusmStatsUnknownUserNames在 LCD 中未找到用户
unsupportedSecurityLevelusmStatsUnsupportedSecLevels用户不支持请求的级别
authenticationFailureusmStatsWrongDigests认证检查失败
notInTimeWindowusmStatsNotInTimeWindows消息在 150 秒窗口之外
decryptionErrorusmStatsDecryptionErrors解密失败

Implementation Notes (实现注意事项)

  1. 状态管理 (State Management): 实现应正确管理和释放 securityStateReference 数据

  2. 报告生成 (Report Generation): 许多错误导致向发送者发送带有适当错误计数器的报告 PDU

  3. 时间同步 (Time Synchronization): 非权威引擎在从权威引擎接收具有更新时间值的消息时自动更新其时间信息

  4. 发现 (Discovery): 非权威引擎可以选择通过在发现期间创建 LCD 条目来了解新引擎

  5. 报告中的安全级别 (Security Level in Reports): 必须使用 securityLevel authNoPriv (而不是 authPriv) 报告 notInTimeWindow 错误, 以允许发送者接收和处理报告