跳到主要内容

3. 过程要素

本节描述了SNMP引擎在根据基于用户的安全模型处理SNMP消息时遵循的安全相关过程。

3.1. 生成传出SNMP消息

本节描述了SNMP引擎每次代表用户以特定securityLevel生成包含管理操作(如请求、响应、通知或报告)的消息时遵循的过程。

  1. a) 如果传递了任何securityStateReference(响应或报告消息),则从cachedSecurityData中提取有关用户的信息。现在可以丢弃cachedSecurityData。securityEngineID设置为本地snmpEngineID。securityLevel设置为调用模块指定的值。

    否则,

    b) 根据securityName,从本地配置数据存储(LCD,usmUserTable)中提取有关目标snmpEngineID(由securityEngineID指定)的用户的信息。如果LCD中缺少有关用户的信息,则向调用模块返回错误指示(unknownSecurityName)。

  2. 如果securityLevel指定消息要防止泄露,但用户不支持身份验证协议和隐私协议,则无法发送消息。向调用模块返回错误指示(unsupportedSecurityLevel)。

  3. 如果securityLevel指定消息要进行身份验证,但用户不支持身份验证协议,则无法发送消息。向调用模块返回错误指示(unsupportedSecurityLevel)。

  4. a) 如果securityLevel指定消息要防止泄露,则根据用户的隐私协议对表示序列化scopedPDU的八位字节序列进行加密。为此,根据抽象原语对实现用户隐私协议的隐私模块进行调用:

    statusInformation =       -- success or failure
    encryptData(
    IN encryptKey -- user's localized privKey
    IN dataToEncrypt -- serialized scopedPDU
    OUT encryptedData -- serialized encryptedPDU
    OUT privParameters -- serialized privacy parameters
    )
    • statusInformation 指示加密过程是否成功。

    • encryptKey 用户的本地化私有privKey是加密算法可以使用的秘密密钥。

    • dataToEncrypt 序列化的scopedPDU是要加密的数据。

    • encryptedData encryptedPDU表示加密的scopedPDU,编码为OCTET STRING。

    • privParameters 隐私参数,编码为OCTET STRING。

    如果隐私模块返回失败,则无法发送消息,并向调用模块返回错误指示(encryptionError)。

    如果隐私模块返回成功,则将返回的privParameters放入securityParameters的msgPrivacyParameters字段中,并且encryptedPDU用作正在准备的消息的有效负载。

    否则,

    b) 如果securityLevel指定消息不需要防止泄露,则将长度为零的OCTET STRING编码到securityParameters的msgPrivacyParameters字段中,明文scopedPDU用作正在准备的消息的有效负载。

  5. securityEngineID被编码为OCTET STRING到securityParameters的msgAuthoritativeEngineID字段中。请注意,对于请求消息,空(长度为零)的securityEngineID是可以的,因为这将导致远程(权威)SNMP引擎返回一个报告PDU,其中包含在返回的报告PDU的securityParameters的msgAuthoritativeEngineID中包含的适当securityEngineID。

  6. a) 如果securityLevel指定消息要进行身份验证,则使用LCD中与securityEngineID对应的snmpEngineBoots和snmpEngineTime的当前值。

    否则,

    b) 如果这是响应或报告消息,则使用LCD中与本地snmpEngineID对应的snmpEngineBoots和snmpEngineTime的当前值。

    否则,

    c) 如果这是请求消息,则对snmpEngineBoots和snmpEngineTime都使用零值。如果snmpEngineID为空,则使用此零值。

    这些值分别被编码为INTEGER到securityParameters的msgAuthoritativeEngineBoots和msgAuthoritativeEngineTime字段中。

  7. userName被编码为OCTET STRING到securityParameters的msgUserName字段中。

  8. a) 如果securityLevel指定消息要进行身份验证,则根据用户的身份验证协议对消息进行身份验证。为此,根据抽象服务原语对实现用户身份验证协议的身份验证模块进行调用:

    statusInformation =
    authenticateOutgoingMsg(
    IN authKey -- the user's localized authKey
    IN wholeMsg -- unauthenticated message
    OUT authenticatedWholeMsg -- authenticated complete message
    )
    • statusInformation 指示身份验证是否成功。

    • authKey 用户的本地化私有authKey是身份验证算法可以使用的秘密密钥。

    • wholeMsg 要进行身份验证的完整序列化消息。

    • authenticatedWholeMsg 与给authenticateOutgoingMsg服务的输入相同,但msgAuthenticationParameters已正确填充。

    如果身份验证模块返回失败,则无法发送消息,并向调用模块返回错误指示(authenticationFailure)。

    如果身份验证模块返回成功,则将msgAuthenticationParameters字段放入securityParameters中,authenticatedWholeMsg表示正在准备的已验证消息的序列化。

    否则,

    b) 如果securityLevel指定消息不需要进行身份验证,则将长度为零的OCTET STRING编码到securityParameters的msgAuthenticationParameters字段中。wholeMsg现在被序列化,然后表示正在准备的未验证消息。

  9. 将完成的消息及其长度返回给调用模块,statusInformation设置为成功。

3.2. 处理传入SNMP消息

本节描述了SNMP引擎每次接收包含代表用户以特定securityLevel执行管理操作的消息时遵循的过程。

为了简化过程要素,并不总是明确指定状态信息的释放。作为一般规则,如果在丢弃消息时状态信息可用,则状态信息也应该被释放。此外,错误指示可以返回递增的计数器的OID和值,并可选地返回securityLevel的值,以及计数器的contextEngineID或contextName的值。此外,如果在检测到错误的点有任何此类信息可用,则返回securityStateReference数据。

  1. 如果接收到的securityParameters不是根据第2.4节中定义的UsmSecurityParameters格式化的OCTET STRING的序列化(根据[RFC3417]的约定),则递增snmpInASNParseErrs计数器[RFC3418],并向调用模块返回错误指示(parseError)。请注意,我们在不返回递增计数器的OID和值的情况下返回,因为在这种情况下没有足够的信息来生成报告PDU。

  2. 从securityParameters中提取安全参数字段的值。要返回给调用者的securityEngineID是msgAuthoritativeEngineID字段的值。准备cachedSecurityData,并准备securityStateReference以引用此数据。要缓存的值为:

    msgUserName

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

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

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

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

  4. 从本地配置数据存储(LCD,usmUserTable)中提取有关msgUserName和msgAuthoritativeEngineID字段值的信息。如果没有关于用户的信息可用,则递增usmStatsUnknownUserNames计数器,并向调用模块返回错误指示(unknownSecurityName)以及递增计数器的OID和值。

  5. 如果有关用户的信息表明它不支持调用者请求的securityLevel,则递增usmStatsUnsupportedSecLevels计数器,并向调用模块返回错误指示(unsupportedSecurityLevel)以及递增计数器的OID和值。

  6. 如果securityLevel指定消息要进行身份验证,则根据用户的身份验证协议对消息进行身份验证。为此,根据抽象服务原语对实现用户身份验证协议的身份验证模块进行调用:

    statusInformation =          -- success or failure
    authenticateIncomingMsg(
    IN authKey -- the user's localized authKey
    IN authParameters -- as received on the wire
    IN wholeMsg -- as received on the wire
    OUT authenticatedWholeMsg -- checked for authentication
    )
    • statusInformation 指示身份验证是否成功。

    • authKey 用户的本地化私有authKey是身份验证算法可以使用的秘密密钥。

    • wholeMsg 要进行身份验证的完整序列化消息。

    • authenticatedWholeMsg 与给authenticateIncomingMsg服务的输入相同,但在检查身份验证之后。

    如果身份验证模块返回失败,则无法信任消息,因此递增usmStatsWrongDigests计数器,并向调用模块返回错误指示(authenticationFailure)以及递增计数器的OID和值。

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

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

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

    - snmpEngineBoots的本地值为2147483647;

    - msgAuthoritativeEngineBoots字段的值与snmpEngineBoots的本地值不同;或,

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

    如果认为消息在时间窗口之外,则递增usmStatsNotInTimeWindows计数器,并向调用模块返回错误指示(notInTimeWindow)以及OID、递增计数器的值以及错误必须以authNoPriv的securityLevel报告的指示

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

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

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

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

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

    - snmpEngineBoots值的本地概念为msgAuthoritativeEngineBoots字段的值,

    - snmpEngineTime值的本地概念为msgAuthoritativeEngineTime字段的值,以及

    - latestReceivedEngineTime为msgAuthoritativeEngineTime字段的值的值。

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

    - snmpEngineBoots值的本地概念为2147483647;

    - msgAuthoritativeEngineBoots字段的值小于snmpEngineBoots值的本地概念;或,

    - msgAuthoritativeEngineBoots字段的值等于snmpEngineBoots值的本地概念,并且msgAuthoritativeEngineTime字段的值比snmpEngineTime值的本地概念小150秒以上。

    如果认为消息在时间窗口之外,则向调用模块返回错误指示(notInTimeWindow)。

    请注意,这意味着已检测到过旧(可能重放)的消息,并认为它是不真实的。

    请注意,此过程允许消息中msgAuthoritativeEngineBoots的值大于snmpEngineBoots值的本地概念,以允许从接收SNMP引擎上次(重新)同步以来已重新启动的权威SNMP引擎接收的消息被接受为真实的。
  8. a) 如果securityLevel指示消息已防止泄露,则根据用户的隐私协议解密表示encryptedPDU的OCTET STRING,以获得未加密的序列化scopedPDU值。为此,根据抽象原语对实现用户隐私协议的隐私模块进行调用:

    statusInformation =       -- success or failure
    decryptData(
    IN decryptKey -- the user's localized privKey
    IN privParameters -- as received on the wire
    IN encryptedData -- encryptedPDU as received
    OUT decryptedData -- serialized decrypted scopedPDU
    )
    • statusInformation 指示解密过程是否成功。

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

    • privParameters msgPrivacyParameters,编码为OCTET STRING。

    • encryptedData encryptedPDU表示加密的scopedPDU,编码为OCTET STRING。

    • decryptedData 如果解密成功,则为序列化的scopedPDU。

    如果隐私模块返回失败,则无法处理消息,因此递增usmStatsDecryptionErrors计数器,并向调用模块返回错误指示(decryptionError)以及递增计数器的OID和值。

    如果隐私模块返回成功,则解密的scopedPDU是要返回给调用模块的消息有效负载。

    否则,

    b) 假定scopedPDU组件为明文,并且是要返回给调用模块的消息有效负载。

  9. 计算maxSizeResponseScopedPDU。这是可能的响应消息的scopedPDU允许的最大大小。为允许与接收到的请求相同的securityLevel的消息头做出了规定。

  10. 从usmUserTable检索用户的securityName。

  11. 将安全数据缓存为cachedSecurityData,以便对此消息的可能响应可以并将使用相同的身份验证和隐私秘密。要保存/缓存的信息如下:

    msgUserName, usmUserAuthProtocol, usmUserAuthKey usmUserPrivProtocol, usmUserPrivKey

  12. 将statusInformation设置为成功,并返回到调用模块,传回processIncomingMsg原语中指定的OUT参数。