跳到主要内容

2. 模型的要素

本节包含实现本备忘录定义的安全模型所需的定义。

2.1. 基于用户的安全模型用户

使用此安全模型的管理操作使用一组定义的用户身份。对于任何在特定SNMP引擎上授权执行管理操作的用户,该SNMP引擎必须了解该用户。希望与另一个SNMP引擎通信的SNMP引擎还必须了解该引擎已知的用户,包括该用户的适用属性的知识。

用户及其属性定义如下:

  • userName 表示用户名的字符串。

  • securityName 一个人类可读的字符串,以独立于安全模型的格式表示用户。userName和securityName之间存在一对一的关系。

  • authProtocol 指示代表该用户发送的消息是否可以进行身份验证,如果可以,则使用的身份验证协议类型。本备忘录中定义了两个这样的协议:

    • HMAC-MD5-96身份验证协议。
    • HMAC-SHA-96身份验证协议。
  • authKey 如果代表该用户发送的消息可以进行身份验证,则与身份验证协议一起使用的(私有)身份验证密钥。请注意,用户的身份验证密钥通常在不同的权威SNMP引擎上会有所不同。authKey无法通过SNMP访问。authKey的长度要求由使用的authProtocol定义。

  • authKeyChange和authOwnKeyChange 远程更新身份验证密钥的唯一方法。以安全的方式执行此操作,因此可以在不需要使用隐私保护的情况下完成更新。

  • privProtocol 指示代表该用户发送的消息是否可以防止泄露,如果可以,则使用的隐私协议类型。本备忘录中定义了一个这样的协议:CBC-DES对称加密协议。

  • privKey 如果代表该用户发送的消息可以进行加密/解密,则与隐私协议一起使用的(私有)隐私密钥。请注意,用户的隐私密钥通常在不同的权威SNMP引擎上会有所不同。privKey无法通过SNMP访问。privKey的长度要求由使用的privProtocol定义。

  • privKeyChange和privOwnKeyChange 远程更新加密密钥的唯一方法。以安全的方式执行此操作,因此可以在不需要使用隐私保护的情况下完成更新。

2.2. 重放保护

每个SNMP引擎维护三个对象:

  • snmpEngineID,它(至少在管理域内)唯一且明确地标识SNMP引擎。

  • snmpEngineBoots,它是自上次配置snmpEngineID以来SNMP引擎重新启动/重新初始化的次数的计数;以及,

  • snmpEngineTime,它是自上次增加snmpEngineBoots计数器以来的秒数。

每个SNMP引擎在其自己的SNMP实体中始终对这些对象具有权威性。非权威SNMP引擎负责根据需要与权威SNMP引擎同步。

权威SNMP引擎需要在非易失性存储中维护其snmpEngineID和snmpEngineBoots的值。

2.2.1. msgAuthoritativeEngineID

经过身份验证的消息中包含的msgAuthoritativeEngineID值用于击败将从一个SNMP引擎到另一个SNMP引擎的消息重放到不同SNMP引擎的攻击。它表示参与消息交换的权威SNMP引擎的snmpEngineID。

当首次安装权威SNMP引擎时,它根据企业特定的算法设置其snmpEngineID的本地值(请参阅SNMP架构文档[RFC3411]中SnmpEngineID文本约定的定义)。

2.2.2. msgAuthoritativeEngineBoots和msgAuthoritativeEngineTime

经过身份验证的消息中包含的msgAuthoritativeEngineBoots和msgAuthoritativeEngineTime值用于击败在消息不再有效时重放消息的攻击。它们表示参与消息交换的权威SNMP引擎的snmpEngineBoots和snmpEngineTime值。

通过使用snmpEngineBoots和snmpEngineTime,不要求SNMP引擎具有即使在SNMP引擎关闭时也会滴答(即随着时间的流逝而增加)的非易失性时钟。相反,每次SNMP引擎重新启动时,它都会检索、递增然后将snmpEngineBoots存储在非易失性存储中,并将snmpEngineTime重置为零。

当首次安装SNMP引擎时,它将snmpEngineBoots和snmpEngineTime的本地值设置为零。如果snmpEngineTime达到其最大值(2147483647),则snmpEngineBoots会递增,就好像SNMP引擎已重新启动,并且snmpEngineTime会重置为零并重新开始递增。

每次权威SNMP引擎重新启动时,持有该权威SNMP引擎的snmpEngineBoots和snmpEngineTime值的任何SNMP引擎在向该权威SNMP引擎发送正确身份验证的消息之前需要重新同步(有关(重新)同步过程,请参阅第2.3节)。但是请注意,这些过程确实规定,当接收SNMP引擎上次(重新)同步以来已重新启动的权威SNMP引擎发送通知时,接收SNMP引擎将接受该通知为真实的。

如果权威SNMP引擎无法确定其最新的snmpEngineBoots值,则它必须将其snmpEngineBoots值设置为2147483647。

每当snmpEngineBoots的本地值具有值2147483647时,它就会锁定在该值,并且经过身份验证的消息总是导致notInTimeWindow身份验证失败。

为了重置snmpEngineBoots值已达到值2147483647的SNMP引擎,需要手动干预。必须物理访问引擎并重新配置它,要么使用新的snmpEngineID值,要么使用该SNMP引擎已知的所有用户的身份验证和隐私协议的新秘密值。请注意,即使SNMP引擎每秒重新启动一次,在达到最大值2147483647之前仍需要大约68年。

2.2.3. 时间窗口

时间窗口是一个值,用于指定代表任何用户生成的消息有效的时间窗口。本备忘录指定对所有用户使用相同的时间窗口值150秒。

2.3. 时间同步

非权威SNMP引擎为了进行真实通信所需的时间同步,在非权威SNMP引擎从权威SNMP引擎获得权威SNMP引擎的snmpEngineBoots和snmpEngineTime值的本地概念时发生。这些值必须(并保持)在权威SNMP引擎的时间窗口内。因此,权威SNMP引擎值的本地概念必须与存储在权威SNMP引擎上的值保持松散同步。除了保留权威SNMP引擎的snmpEngineBoots和snmpEngineTime的本地副本外,非权威SNMP引擎还必须保留一个本地变量latestReceivedEngineTime。此值记录非权威SNMP引擎从权威SNMP引擎接收到的snmpEngineTime的最高值,并用于消除重放消息的可能性,这些消息将阻止非权威SNMP引擎的snmpEngineTime概念前进。

非权威SNMP引擎必须为其希望与之通信的每个权威SNMP引擎保留这些值(snmpEngineBoots、snmpEngineTime和latestReceivedEngineTime)的本地概念。由于每个权威SNMP引擎都由其snmpEngineID值唯一且明确地标识,因此非权威SNMP引擎可以使用此值作为键来缓存其这些值的本地概念。

时间同步作为接收SNMP消息的过程的一部分发生(第3.2节,步骤7b)。因此,非权威SNMP引擎不需要显式的时间同步过程。请注意,每当snmpEngineID的本地值发生更改时(例如,通过发现)或首次与权威SNMP引擎建立安全通信时,应将snmpEngineBoots和latestReceivedEngineTime的本地值设置为零。这将导致在接收到下一个真实消息时进行时间同步。

2.4. 使用此安全模型的SNMP消息

使用此安全模型的SNMP消息的语法遵循版本特定的消息处理模型文档中定义的消息格式(例如[RFC3412])。

SNMPv3消息中的字段msgSecurityParameters的数据类型为OCTET STRING。其值是以下ASN.1序列的BER序列化:

USMSecurityParametersSyntax DEFINITIONS IMPLICIT TAGS ::= BEGIN

UsmSecurityParameters ::=
SEQUENCE {
-- global User-based security parameters
msgAuthoritativeEngineID OCTET STRING,
msgAuthoritativeEngineBoots INTEGER (0..2147483647),
msgAuthoritativeEngineTime INTEGER (0..2147483647),
msgUserName OCTET STRING (SIZE(0..32)),
-- authentication protocol specific parameters
msgAuthenticationParameters OCTET STRING,
-- privacy protocol specific parameters
msgPrivacyParameters OCTET STRING
}
END

此序列的字段为:

  • msgAuthoritativeEngineID指定参与消息交换的权威SNMP引擎的snmpEngineID。

  • msgAuthoritativeEngineBoots指定参与消息交换的权威SNMP引擎的snmpEngineBoots值。

  • msgAuthoritativeEngineTime指定参与消息交换的权威SNMP引擎的snmpEngineTime值。

  • msgUserName指定代表其交换消息的用户(主体)。请注意,长度为零的userName将不匹配任何用户,但可用于snmpEngineID发现。

  • msgAuthenticationParameters由消息使用的身份验证协议定义,如usmUserTable中用户条目的usmUserAuthProtocol列所定义。

  • msgPrivacyParameters由消息使用的隐私协议定义,如usmUserTable中用户条目的usmUserPrivProtocol列所定义。

有关字段msgSecurityParameters的BER编码示例,请参阅附录A.4。

2.5. 基于用户的安全模型提供的服务

本节描述了基于用户的安全模型及其输入和输出提供的服务。

这些服务被描述为抽象服务接口的原语,输入和输出被描述为在这些抽象服务原语中传递的抽象数据元素。

2.5.1. 用于生成传出SNMP消息的服务

当消息处理(MP)子系统调用基于用户的安全模块来保护传出SNMP消息时,它必须使用安全模块提供的适当服务。提供以下两种服务:

  1. 生成请求消息的服务。抽象服务原语是:
statusInformation =            -- success or errorIndication
generateRequestMsg(
IN messageProcessingModel -- typically, SNMP version
IN globalData -- message header, admin data
IN maxMessageSize -- of the sending SNMP entity
IN securityModel -- for the outgoing message
IN securityEngineID -- authoritative SNMP entity
IN securityName -- on behalf of this principal
IN securityLevel -- Level of Security requested
IN scopedPDU -- message (plaintext) payload
OUT securityParameters -- filled in by Security Module
OUT wholeMsg -- complete generated message
OUT wholeMsgLength -- length of generated message
)
  1. 生成响应消息的服务。抽象服务原语是:
statusInformation =            -- success or errorIndication
generateResponseMsg(
IN messageProcessingModel -- typically, SNMP version
IN globalData -- message header, admin data
IN maxMessageSize -- of the sending SNMP entity
IN securityModel -- for the outgoing message
IN securityEngineID -- authoritative SNMP entity
IN securityName -- on behalf of this principal
IN securityLevel -- Level of Security requested
IN scopedPDU -- message (plaintext) payload
IN securityStateReference -- reference to security state
-- information from original
-- request
OUT securityParameters -- filled in by Security Module
OUT wholeMsg -- complete generated message
OUT wholeMsgLength -- length of generated message
)

在抽象服务原语中作为参数传递的抽象数据元素如下:

  • statusInformation 指示消息的编码和保护是否成功。如果不成功,则是问题的指示。

  • messageProcessingModel 要生成的消息的SNMP版本号。基于用户的安全模块不使用此数据。

  • globalData 消息头(即其管理信息)。基于用户的安全模块不使用此数据。

  • maxMessageSize 消息中包含的最大消息大小。基于用户的安全模块不使用此数据。

  • securityParameters 这些是安全参数。它们将由基于用户的安全模块填充。

  • securityModel 使用的安全模型。应该是基于用户的安全模型。基于用户的安全模块不使用此数据。

  • securityName 与snmpEngineID一起,它标识usmUserTable中要用于保护消息的行。securityName的格式独立于安全模型。在响应的情况下,此参数将被忽略,并使用缓存中的值。

  • securityLevel 安全级别,基于用户的安全模块从中确定消息是否需要防止泄露以及消息是否需要进行身份验证。

  • securityEngineID 要向其发送数据请求消息的权威SNMP引擎的snmpEngineID。在响应的情况下,它隐含为处理SNMP引擎的snmpEngineID,因此如果指定了它,则将被忽略。

  • scopedPDU 消息有效负载。就基于用户的安全模型而言,数据是不透明的。

  • securityStateReference 在保护传出响应消息时要使用的cachedSecurityData的句柄/引用。这是在处理此响应消息所针对的传入请求消息时由基于用户的安全模块生成的完全相同的句柄/引用。

  • wholeMsg 完全编码和保护的消息,准备在线路上发送。

  • wholeMsgLength 编码和保护的消息(wholeMsg)的长度。

完成该过程后,基于用户的安全模块返回statusInformation。如果该过程成功,则返回完整的消息,如果指定的securityLevel请求,则应用隐私和身份验证。如果该过程不成功,则返回errorIndication。

2.5.2. 用于处理传入SNMP消息的服务

当消息处理(MP)子系统调用基于用户的安全模块来验证传入消息的适当安全性时,它必须使用为传入消息提供的服务。抽象服务原语是:

statusInformation =             -- errorIndication or success
-- error counter OID/value if error
processIncomingMsg(
IN messageProcessingModel -- typically, SNMP version
IN maxMessageSize -- of the sending SNMP entity
IN securityParameters -- for the received message
IN securityModel -- for the received message
IN securityLevel -- Level of Security
IN wholeMsg -- as received on the wire
IN wholeMsgLength -- length as received on the wire
OUT securityEngineID -- authoritative SNMP entity
OUT securityName -- identification of the principal
OUT scopedPDU, -- message (plaintext) payload
OUT maxSizeResponseScopedPDU -- maximum size of the Response PDU
OUT securityStateReference -- reference to security state
) -- information, needed for response

在抽象服务原语中作为参数传递的抽象数据元素如下:

  • statusInformation 指示该过程是否成功。如果不成功,则statusInformation包括已递增的错误计数器的OID和值。

  • messageProcessingModel 消息中接收的SNMP版本号。基于用户的安全模块不使用此数据。

  • maxMessageSize 消息中包含的最大消息大小。基于用户的安全模块使用此值来计算maxSizeResponseScopedPDU。

  • securityParameters 这些是消息中接收的安全参数。

  • securityModel 使用的安全模型。应该是基于用户的安全模型。基于用户的安全模块不使用此数据。

  • securityLevel 安全级别,基于用户的安全模块从中确定消息是否需要防止泄露以及消息是否需要进行身份验证。

  • wholeMsg 接收的完整消息。

  • wholeMsgLength 接收的消息(wholeMsg)的长度。

  • securityEngineID 从msgAuthoritativeEngineID字段提取的snmpEngineID,用于在usmUserTable中查找秘密。

  • securityName 表示代表其接收消息的用户的安全名称。securityName的格式独立于安全模型。

  • scopedPDU 消息有效负载。就基于用户的安全模型而言,数据是不透明的。

  • maxSizeResponseScopedPDU 要包含在可能的响应消息中的scopedPDU的最大大小。基于用户的安全模块根据msgMaxSize(在消息中接收)和此类响应消息的消息头(包括securityParameters)所需的空间计算此大小。

  • securityStateReference 在保护传出响应消息时要使用的cachedSecurityData的句柄/引用。当消息处理子系统调用基于用户的安全模块为此传入消息生成响应时,它必须传递此句柄/引用。

完成该过程后,基于用户的安全模块返回statusInformation,如果该过程成功,则返回用于进一步处理消息的其他数据元素。如果该过程不成功,则返回errorIndication,可能还有已递增的错误计数器的OID和值对。

2.6. 密钥本地化算法

本地化密钥是用户U和一个权威SNMP引擎E之间共享的秘密密钥。即使用户可能只有一个密码,因此整个网络只有一个密钥,但用户和每个权威SNMP引擎之间共享的实际秘密将是不同的。这是通过密钥本地化[Localized-key]实现的。

首先,如果用户使用密码,则使用附录A.2.1和A.2.2中描述的两种算法之一将用户的密码转换为密钥Ku。

要将密钥Ku转换为用户U在权威SNMP引擎E的本地化密钥Kul,将权威SNMP引擎的snmpEngineID附加到密钥Ku,然后将密钥Ku附加到结果,从而将snmpEngineID包裹在用户密钥Ku的两个副本中。然后运行安全哈希函数(使用哪个取决于为此权威SNMP引擎E上的此用户U定义的身份验证协议;本文档定义了两个身份验证协议及其基于MD5和SHA的关联算法)。哈希函数的输出是用户U在权威SNMP引擎E的本地化密钥Kul。