1. 前言部分
SNMPv3与SNMPv2相比有了很大的改进,主要体现在安全性方面:
-
用户认证机制 - SNMPv3改用基于用户的安全模型(USM),需要替换v2中的社区字符串认证机制(community strings),实现用户管理、认证和加密。
-
加密与数据完整性检查 - 需要添加支持加密传输和数据完整性检查的模块,如SHA、MD5等算法。v2没有加密机制。
-
授权与访问控制 - 添加基于视图(view-based access control,VACM)的访问控制模型模块以及授权处理。以控制访问 SNMP 代理的哪些数据。
-
安全参数与配置 - 添加安全级别参数设置、安全密钥配置等与安全相关的数据结构与存储。
-
消息处理过程 - message handling processes中加入处理安全参数、认证、加密与解密、授权检查等步骤
主要是在安全性、认证、加密、访问控制等方面下功夫,与SNMPv2形成明显对比。这需要对原有的代码流程进行较大的修改。
2. 模型元素
根据RFC3414规范,SNMPv3在用户安全模型(USM)方面做了如下的关键定义:
USM Users
定义了用户的数据模型,包括用户名称、认证协议算法、本地化密钥等安全相关的参数。这是基于用户实现安全性的基础,包括:
-
userName:用户名称
-
securityName:与模型无关的安全名称
-
authProtocol:认证协议
-
authKey:认证密钥
-
authKeyChange:远程更新认证密钥
-
privProtocol:隐私保护协议
-
privKey:隐私保护密钥
-
privKeyChange:远程更新隐私保护密钥
这些属性中,有的用于标识用户,有的则定义了保证安全性所需要的密钥、认证协议等信息。
注意每种密钥可基于不同设备配置不同值,且不能通过SNMP本身读取,只能通过特定安全机制来远程更新。
重放保护机制
定义了时间同步机制,防止重放攻击。
- 每个SNMP引擎维护了三个对象:
-
snmpEngineID:唯一标识一个SNMP引擎
-
snmpEngineBoots:启动计数器
-
snmpEngineTime:运行时间计数器
-
引入了msgAuthoritativeEngineID参数,包含权威引擎ID,用于防重放攻击。
-
同步沿用了snmpEngineBoots和snmpEngineTime的值,以识别过期消息。
-
描述了初始值配置,时钟回拨,时钟同步的处理过程。非权威引擎需要同步这些值。
-
定义了时间窗口的概念,在该窗口内的消息被视为有效。
-
详细阐述了时钟同步的过程,即接收端获取最新权威时钟计数器,并检查其落在时间窗口内。
工作流程是:
-
消息中包含上面三个参数的值。
-
接收方根据这些参数,判断消息是否为重放旧消息。
-
同时根据权威引擎同步最新计数器值。
这种基于引擎唯一ID和计数器的防重放机制可以确保安全性。
USM消息格式
定义了USM安全参数的数据格式,包含关键安全参数元素的ASN.1格式,以便消息传递。
SNMPv3消息格式遵循version-specific的消息处理模型文档定义,如RFC3412。
msgSecurityParameters字段采用OCTET STRING类型,值为USMSecurityParameters 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(1..32)),
-- authentication protocol specific parameters
msgAuthenticationParameters OCTET STRING,
-- privacy protocol specific parameters
msgPrivacyParameters OCTET STRING
}
END
USM安全参数(msgSecurityParameters)中各个字段的具体含义:
-
msgAuthoritativeEngineID:授权的引擎ID,表示本次消息交互涉及的授权SNMP引擎的标识符。
-
msgAuthoritativeEngineBoots:授权引擎的启动计数器,用于重放保护检测。
-
msgAuthoritativeEngineTime: 授权引擎的时间计数器,用于重放保护。
-
msgUserName: 代表本次消息的用户名称。如果为空则仅用于引擎ID发现。
-
msgAuthenticationParameters:根据usmUserTable中配置的认证协议的参数。
-
msgPrivacyParameters:根据usmUserTable中配置的隐私保护协议的参数。
USM服务接口
定义了USM的服务接口,包括生成请求和响应消息的服务原语。这为USM模块提供了标准化接口。
Outgoing SNMP Message
主要描述了USM模块为SNMP消息处理(Message Processing)子系统生成外发SNMP消息所提供的服务和数据元素。
包含了两个服务:
-
generateRequestMsg: 生成Request请求消息
-
generateResponseMsg: 生成Response响应消息
1) A service to generate a Request message. The abstract service primitive is:
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
)
2) A service to generate a Response message. The abstract service primitive is:
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
)
Note: 这只是概念上的抽象服务接口,具体的实现可能因编程语言和平台而异。
这部分定义了USM模块生成安全性SNMP消息服务接口的参数和元素,主要有以下几类:
-
messageProcessingModel:SNMP版本等信息
-
securityModel/Level/Name/ID:安全模型和级别相关信息
-
scopedPDU:实际的消息 payload
-
securityStateReference: 对response消息的cache引用
-
statusInformation:返回生成消息的状态
-
securityParameters:安全参数,由USM填充
-
wholeMsg:生成的完整消息
密钥本地化
这部分描述了密钥本地化(Key Localization)的算法,目的是使得不同设备上同一用户的实际密钥可以不同,提高安全性。其流程是:
-
用户的密码先通过哈希算法转换为一个主密钥Ku。附录给出了MD5和SHA两种算法。
-
然后,将授权引擎E的snmpEngineID追加到Ku后面,再将Ku追加到上一步的结果后面。这样就把snmpEngineID包裹在两个Ku之间。
-
最后调用安全哈希算法(根据用户U在引擎E上的配置的认证协议选择是MD5还是SHA),输入为上一步的拼接结果。输出hash后的值就是用户U在该引擎E上的最终本地化密钥Kul。
这样不同设备根据各自的snmpEngineID,通过hash计算都可以得到不同的本地化密钥,提高了安全性,防止主密钥泄露后被全局利用。
3. 过程元素
描述了SNMP(简单网络管理协议)收到一个代表用户的带有特定安全级别的管理操作的消息时遵循的消息发送和接收端的处理流程。
Generating an Outgoing SNMP Message
具体步骤包括:
-
基于安全状态引用或安全名称提取用户信息。
-
检查安全级别是否规定消息需要被保护免于泄露,以及用户是否支持认证和隐私协议。
-
检查安全级别是否规定消息需要被认证,以及用户是否支持认证协议。
-
如果安全级别规定消息需要被保护免于泄露,就对消息进行加密。
-
将securityEngineID编码为OCTET STRING,然后放入securityParameters的msgAuthoritativeEngineID字段。
-
如果安全级别规定消息需要被认证,就使用来自LCD的securityEngineID对应的snmpEngineBoots和snmpEngineTime的当前值。
-
将userName编码为OCTET STRING,然后放入securityParameters的msgUserName字段。
-
如果安全级别规定消息需要被认证,就根据用户的认证协议对消息进行认证。
-
将完成的消息及其长度返回给调用模块,同时将statusInformation设置为成功。
Processing an Incoming SNMP Message
具体步骤包括:
-
检查收到的securityParameters是否为UsmSecurityParameters定义的OCTET STRING格式的序列化。如果不是,则增加snmpInASNParseErrs计数器,并返回错误指示(parseError)给调用模块。
-
从securityParameters中提取安全参数字段的值。返回给调用者的securityEngineID的值是msgAuthoritativeEngineID字段的值。准备cachedSecurityData并准备一个securityStateReference来引用这些数据。需要缓存的值包括:msgUserName。
-
如果securityParameters中msgAuthoritativeEngineID字段的值未知,则有两种选择:a) 执行发现的非权威SNMP引擎可以选择在其本地配置数据存储(LCD)中创建一个新条目并继续处理;或者b) 增加usmStatsUnknownEngineIDs计数器,并返回一个错误指示(unknownEngineID)以及增加计数器的OID和值给调用模块。
-
从本地配置数据存储(LCD, usmUserTable)中提取msgUserName和msgAuthoritativeEngineID字段的值的信息。如果没有关于用户的信息,那么usmStatsUnknownUserNames计数器将会增加,并且一个错误指示(unknownSecurityName)以及增加计数器的OID和值将会返回给调用模块。
-
如果用户的信息表明用户不支持调用者请求的securityLevel,那么usmStatsUnsupportedSecLevels计数器将会增加,并且一个错误指示(unsupportedSecurityLevel)以及增加计数器的OID和值将会返回给调用模块。
-
如果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
)
如果认证模块返回失败,那么消息不能被信任,因此usmStatsWrongDigests计数器会增加,并且一个错误指示(authenticationFailure)以及增加计数器的OID和值将会返回给调用模块。如果认证模块返回成功,那么消息是真实的并且可以被信任,因此继续处理。
- 根据用户认证协议的认证模块的判断,做出不同的处理
检查时间窗口:
- 如果消息是经过身份验证的,从本地配置数据存储中提取与 msgAuthoritativeEngineID 相关的本地值。
- 如果消息来自授权的 SNMP 引擎,检查时间窗口条件:
- 如果满足任一条件(本地 snmpEngineBoots 为最大值、msgAuthoritativeEngineBoots 与本地值不同、msgAuthoritativeEngineTime 与本地 snmpEngineTime 差异大于 +/- 150 秒),则认为消息不在时间窗口内。
- 在消息不在时间窗口内的情况下,增加错误计数器并返回错误指示(notInTimeWindow)。
处理非授权的 SNMP 引擎情况:
- 如果消息来自非授权的 SNMP 引擎,执行以下步骤:
- 如果条件满足(msgAuthoritativeEngineBoots 大于本地值或者等于本地值但 msgAuthoritativeEngineTime 大于 latestReceivedEngineTime),则更新本地配置数据存储的相关值。
- 如果条件满足(本地 snmpEngineBoots 为最大值、msgAuthoritativeEngineBoots 小于本地值、或者msgAuthoritativeEngineBoots 等于本地值但 msgAuthoritativeEngineTime 与本地 snmpEngineTime 差异大于 150 秒),则认为消息不在时间窗口内。
- 在消息不在时间窗口内的情况下,返回错误指示(notInTimeWindow)。
- 如果securityLevel指示消息被保护免于泄露,那么根据用户的隐私协议对表示序列化scopedPDU的字节序列进行解密,以获得未加密的序列化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
)
如果隐私模块返回失败,那么消息不能被处理,因此usmStatsDecryptionErrors计数器会增加,并且一个错误指示(decryptionError)以及增加计数器的OID和值将会返回给调用模块。如果隐私模块返回成功,那么解密的scopedPDU是要返回给调用模块的消息有效载荷。否则,假定scopedPDU组件是明文,并且是要返回给调用模块的消息有效载荷。
-
计算 maxSizeResponseScopedPDU,这是可能的响应消息的 scopedPDU 允许的最大大小。
-
从 usmUserTable 中检索用户的 securityName。
-
将安全数据缓存为 cachedSecurityData,以便对该消息的可能响应可以使用相同的身份验证和隐私密钥。
-
将 statusInformation 设置为 success,并根据 processIncomingMsg 原语中指定的 OUT 参数返回到调用模块。
4. 发现过程
这段文本描述了用户安全模型(User-based Security Model)中的发现过程。
-
发现需求: 用户安全模型要求进行发现过程,以获取有关其他 SNMP 引擎的足够信息,以便与它们进行通信。发现需要一个非授权的 SNMP 引擎在通信之前了解授权的 SNMP 引擎的 snmpEngineID 值。可以通过生成一个带有 securityLevel 为 noAuthNoPriv、msgUserName 为空、msgAuthoritativeEngineID 为零长度、以及 varBindList 为空的 Request 消息来实现。对这条消息的响应将是一个 Report 消息,其中包含授权的 SNMP 引擎的 snmpEngineID 作为 msgSecurityParameters 字段内 msgAuthoritativeEngineID 字段的值。它包含一个带有 varBindList 中的 usmStatsUnknownEngineIDs 计数器的 Report PDU。
-
需要身份验证的通信: 如果需要身份验证通信,发现过程还应该与授权的 SNMP 引擎建立时间同步。可以通过发送一个经过身份验证的 Request 消息,其中 msgAuthoritativeEngineID 的值设置为新学到的 snmpEngineID,msgAuthoritativeEngineBoots 和 msgAuthoritativeEngineTime 的值设置为零来实现。对于经过身份验证的 Request 消息,必须在 msgUserName 字段中使用有效的 userName。对这条经过身份验证的消息的响应将是一个 Report 消息,其中包含授权的 SNMP 引擎的 snmpEngineBoots 和 snmpEngineTime 的最新值,分别作为 msgAuthoritativeEngineBoots 和 msgAuthoritativeEngineTime 字段的值。它还包含 Report PDU 的 varBindList 中的 usmStatsNotInTimeWindows 计数器。然后,时间同步会自动发生,作为处理 非授权的 SNMP 引擎情况程序 的一部分。另请参阅第 2.3 节。
5. 定义
关键的数据结构和元素的规范定义
点击查看代码
SNMP-USER-BASED-SM-MIB DEFINITIONS ::= BEGIN
IMPORTS
MODULE-IDENTITY, OBJECT-TYPE,
OBJECT-IDENTITY,
snmpModules, Counter32 FROM SNMPv2-SMI
TEXTUAL-CONVENTION, TestAndIncr,
RowStatus, RowPointer,
StorageType, AutonomousType FROM SNMPv2-TC
MODULE-COMPLIANCE, OBJECT-GROUP FROM SNMPv2-CONF
SnmpAdminString, SnmpEngineID,
snmpAuthProtocols, snmpPrivProtocols FROM SNMP-FRAMEWORK-MIB;
snmpUsmMIB MODULE-IDENTITY
LAST-UPDATED "200210160000Z" -- 16 Oct 2002, midnight
ORGANIZATION "SNMPv3 Working Group"
CONTACT-INFO "WG-email: [email protected]
Subscribe: [email protected]
In msg body: subscribe snmpv3
Chair: Russ Mundy
Network Associates Laboratories
postal: 15204 Omega Drive, Suite 300
Rockville, MD 20850-4601
USA
email: [email protected]
phone: +1 301-947-7107
Co-Chair: David Harrington
Enterasys Networks
Postal: 35 Industrial Way
P. O. Box 5004
Rochester, New Hampshire 03866-5005
USA
EMail: [email protected]
Phone: +1 603-337-2614
Co-editor Uri Blumenthal
Lucent Technologies
postal: 67 Whippany Rd.
Whippany, NJ 07981
USA
email: [email protected]
phone: +1-973-386-2163
Co-editor: Bert Wijnen
Lucent Technologies
postal: Schagen 33
3461 GL Linschoten
Netherlands
email: [email protected]
phone: +31-348-480-685
"
DESCRIPTION "The management information definitions for the
SNMP User-based Security Model.
Copyright (C) The Internet Society (2002). This
version of this MIB module is part of RFC 3414;
see the RFC itself for full legal notices.
"
-- Revision history
REVISION "200210160000Z" -- 16 Oct 2002, midnight
DESCRIPTION "Changes in this revision:
- Updated references and contact info.
- Clarification to usmUserCloneFrom DESCRIPTION
clause
- Fixed 'command responder' into 'command generator'
in last para of DESCRIPTION clause of
usmUserTable.
This revision published as RFC3414.
"
REVISION "199901200000Z" -- 20 Jan 1999, midnight
DESCRIPTION "Clarifications, published as RFC2574"
REVISION "199711200000Z" -- 20 Nov 1997, midnight
DESCRIPTION "Initial version, published as RFC2274"
::= { snmpModules 15 }
-- Administrative assignments ****************************************
usmMIBObjects OBJECT IDENTIFIER ::= { snmpUsmMIB 1 }
usmMIBConformance OBJECT IDENTIFIER ::= { snmpUsmMIB 2 }
-- Identification of Authentication and Privacy Protocols ************
usmNoAuthProtocol OBJECT-IDENTITY
STATUS current
DESCRIPTION "No Authentication Protocol."
::= { snmpAuthProtocols 1 }
usmHMACMD5AuthProtocol OBJECT-IDENTITY
STATUS current
DESCRIPTION "The HMAC-MD5-96 Digest Authentication Protocol."
REFERENCE "- H. Krawczyk, M. Bellare, R. Canetti HMAC:
Keyed-Hashing for Message Authentication,
RFC2104, Feb 1997.
- Rivest, R., Message Digest Algorithm MD5, RFC1321.
"
::= { snmpAuthProtocols 2 }
usmHMACSHAAuthProtocol OBJECT-IDENTITY
STATUS current
DESCRIPTION "The HMAC-SHA-96 Digest Authentication Protocol."
REFERENCE "- H. Krawczyk, M. Bellare, R. Canetti, HMAC:
Keyed-Hashing for Message Authentication,
RFC2104, Feb 1997.
- Secure Hash Algorithm. NIST FIPS 180-1.
"
::= { snmpAuthProtocols 3 }
usmNoPrivProtocol OBJECT-IDENTITY
STATUS current
DESCRIPTION "No Privacy Protocol."
::= { snmpPrivProtocols 1 }
usmDESPrivProtocol OBJECT-IDENTITY
STATUS current
DESCRIPTION "The CBC-DES Symmetric Encryption Protocol."
REFERENCE "- Data Encryption Standard, National Institute of
Standards and Technology. Federal Information
Processing Standard (FIPS) Publication 46-1.
Supersedes FIPS Publication 46,
(January, 1977; reaffirmed January, 1988).
- Data Encryption Algorithm, American National
Standards Institute. ANSI X3.92-1981,
(December, 1980).
- DES Modes of Operation, National Institute of
Standards and Technology. Federal Information
Processing Standard (FIPS) Publication 81,
(December, 1980).
- Data Encryption Algorithm - Modes of Operation,
American National Standards Institute.
ANSI X3.106-1983, (May 1983).
"
::= { snmpPrivProtocols 2 }
-- Textual Conventions ***********************************************
KeyChange ::= TEXTUAL-CONVENTION
STATUS current
DESCRIPTION
"Every definition of an object with this syntax must identify
a protocol P, a secret key K, and a hash algorithm H
that produces output of L octets.
The object's value is a manager-generated, partially-random
value which, when modified, causes the value of the secret
key K, to be modified via a one-way function.
The value of an instance of this object is the concatenation
of two components: first a 'random' component and then a
'delta' component.
The lengths of the random and delta components
are given by the corresponding value of the protocol P;
if P requires K to be a fixed length, the length of both the
random and delta components is that fixed length; if P
allows the length of K to be variable up to a particular
maximum length, the length of the random component is that
maximum length and the length of the delta component is any
length less than or equal to that maximum length.
For example, usmHMACMD5AuthProtocol requires K to be a fixed
length of 16 octets and L - of 16 octets.
usmHMACSHAAuthProtocol requires K to be a fixed length of
20 octets and L - of 20 octets. Other protocols may define
other sizes, as deemed appropriate.
When a requester wants to change the old key K to a new
key keyNew on a remote entity, the 'random' component is
obtained from either a true random generator, or from a
pseudorandom generator, and the 'delta' component is
computed as follows:
- a temporary variable is initialized to the existing value
of K;
- if the length of the keyNew is greater than L octets,
then:
- the random component is appended to the value of the
temporary variable, and the result is input to the
the hash algorithm H to produce a digest value, and
the temporary variable is set to this digest value;
- the value of the temporary variable is XOR-ed with
the first (next) L-octets (16 octets in case of MD5)
of the keyNew to produce the first (next) L-octets
(16 octets in case of MD5) of the 'delta' component.
- the above two steps are repeated until the unused
portion of the keyNew component is L octets or less,
- the random component is appended to the value of the
temporary variable, and the result is input to the
hash algorithm H to produce a digest value;
- this digest value, truncated if necessary to be the same
length as the unused portion of the keyNew, is XOR-ed
with the unused portion of the keyNew to produce the
(final portion of the) 'delta' component.
For example, using MD5 as the hash algorithm H:
iterations = (lenOfDelta - 1)/16; /* integer division */
temp = keyOld;
for (i = 0; i < iterations; i++) {
temp = MD5 (temp || random);
delta[i*16 .. (i*16)+15] =
temp XOR keyNew[i*16 .. (i*16)+15];
}
temp = MD5 (temp || random);
delta[i*16 .. lenOfDelta-1] =
temp XOR keyNew[i*16 .. lenOfDelta-1];
The 'random' and 'delta' components are then concatenated as
described above, and the resulting octet string is sent to
the recipient as the new value of an instance of this object.
At the receiver side, when an instance of this object is set
to a new value, then a new value of K is computed as follows:
- a temporary variable is initialized to the existing value
of K;
- if the length of the delta component is greater than L
octets, then:
- the random component is appended to the value of the
temporary variable, and the result is input to the
hash algorithm H to produce a digest value, and the
temporary variable is set to this digest value;
- the value of the temporary variable is XOR-ed with
the first (next) L-octets (16 octets in case of MD5)
of the delta component to produce the first (next)
L-octets (16 octets in case of MD5) of the new value
of K.
- the above two steps are repeated until the unused
portion of the delta component is L octets or less,
- the random component is appended to the value of the
temporary variable, and the result is input to the
hash algorithm H to produce a digest value;
- this digest value, truncated if necessary to be the same
length as the unused portion of the delta component, is
XOR-ed with the unused portion of the delta component to
produce the (final portion of the) new value of K.
For example, using MD5 as the hash algorithm H:
iterations = (lenOfDelta - 1)/16; /* integer division */
temp = keyOld;
for (i = 0; i < iterations; i++) {
temp = MD5 (temp || random);
keyNew[i*16 .. (i*16)+15] =
temp XOR delta[i*16 .. (i*16)+15];
}
temp = MD5 (temp || random);
keyNew[i*16 .. lenOfDelta-1] =
temp XOR delta[i*16 .. lenOfDelta-1];
The value of an object with this syntax, whenever it is
retrieved by the management protocol, is always the zero
length string.
Note that the keyOld and keyNew are the localized keys.
Note that it is probably wise that when an SNMP entity sends
a SetRequest to change a key, that it keeps a copy of the old
key until it has confirmed that the key change actually
succeeded.
"
SYNTAX OCTET STRING
-- Statistics for the User-based Security Model **********************
usmStats OBJECT IDENTIFIER ::= { usmMIBObjects 1 }
usmStatsUnsupportedSecLevels OBJECT-TYPE
SYNTAX Counter32
MAX-ACCESS read-only
STATUS current
DESCRIPTION "The total number of packets received by the SNMP
engine which were dropped because they requested a
securityLevel that was unknown to the SNMP engine
or otherwise unavailable.
"
::= { usmStats 1 }
usmStatsNotInTimeWindows OBJECT-TYPE
SYNTAX Counter32
MAX-ACCESS read-only
STATUS current
DESCRIPTION "The total number of packets received by the SNMP
engine which were dropped because they appeared
outside of the authoritative SNMP engine's window.
"
::= { usmStats 2 }
usmStatsUnknownUserNames OBJECT-TYPE
SYNTAX Counter32
MAX-ACCESS read-only
STATUS current
DESCRIPTION "The total number of packets received by the SNMP
engine which were dropped because they referenced a
user that was not known to the SNMP engine.
"
::= { usmStats 3 }
usmStatsUnknownEngineIDs OBJECT-TYPE
SYNTAX Counter32
MAX-ACCESS read-only
STATUS current
DESCRIPTION "The total number of packets received by the SNMP
engine which were dropped because they referenced an
snmpEngineID that was not known to the SNMP engine.
"
::= { usmStats 4 }
usmStatsWrongDigests OBJECT-TYPE
SYNTAX Counter32
MAX-ACCESS read-only
STATUS current
DESCRIPTION "The total number of packets received by the SNMP
engine which were dropped because they didn't
contain the expected digest value.
"
::= { usmStats 5 }
usmStatsDecryptionErrors OBJECT-TYPE
SYNTAX Counter32
MAX-ACCESS read-only
STATUS current
DESCRIPTION "The total number of packets received by the SNMP
engine which were dropped because they could not be
decrypted.
"
::= { usmStats 6 }
-- The usmUser Group ************************************************
usmUser OBJECT IDENTIFIER ::= { usmMIBObjects 2 }
usmUserSpinLock OBJECT-TYPE
SYNTAX TestAndIncr
MAX-ACCESS read-write
STATUS current
DESCRIPTION "An advisory lock used to allow several cooperating
Command Generator Applications to coordinate their
use of facilities to alter secrets in the
usmUserTable.
"
::= { usmUser 1 }
-- The table of valid users for the User-based Security Model ********
usmUserTable OBJECT-TYPE
SYNTAX SEQUENCE OF UsmUserEntry
MAX-ACCESS not-accessible
STATUS current
DESCRIPTION "The table of users configured in the SNMP engine's
Local Configuration Datastore (LCD).
To create a new user (i.e., to instantiate a new
conceptual row in this table), it is recommended to
follow this procedure:
1) GET(usmUserSpinLock.0) and save in sValue.
2) SET(usmUserSpinLock.0=sValue,
usmUserCloneFrom=templateUser,
usmUserStatus=createAndWait)
You should use a template user to clone from
which has the proper auth/priv protocol defined.
If the new user is to use privacy:
3) generate the keyChange value based on the secret
privKey of the clone-from user and the secret key
to be used for the new user. Let us call this
pkcValue.
4) GET(usmUserSpinLock.0) and save in sValue.
5) SET(usmUserSpinLock.0=sValue,
usmUserPrivKeyChange=pkcValue
usmUserPublic=randomValue1)
6) GET(usmUserPulic) and check it has randomValue1.
If not, repeat steps 4-6.
If the new user will never use privacy:
7) SET(usmUserPrivProtocol=usmNoPrivProtocol)
If the new user is to use authentication:
8) generate the keyChange value based on the secret
authKey of the clone-from user and the secret key
to be used for the new user. Let us call this
akcValue.
9) GET(usmUserSpinLock.0) and save in sValue.
10) SET(usmUserSpinLock.0=sValue,
usmUserAuthKeyChange=akcValue
usmUserPublic=randomValue2)
11) GET(usmUserPulic) and check it has randomValue2.
If not, repeat steps 9-11.
If the new user will never use authentication:
12) SET(usmUserAuthProtocol=usmNoAuthProtocol)
Finally, activate the new user:
13) SET(usmUserStatus=active)
The new user should now be available and ready to be
used for SNMPv3 communication. Note however that access
to MIB data must be provided via configuration of the
SNMP-VIEW-BASED-ACM-MIB.
The use of usmUserSpinlock is to avoid conflicts with
another SNMP command generator application which may
also be acting on the usmUserTable.
"
::= { usmUser 2 }
usmUserEntry OBJECT-TYPE
SYNTAX UsmUserEntry
MAX-ACCESS not-accessible
STATUS current
DESCRIPTION "A user configured in the SNMP engine's Local
Configuration Datastore (LCD) for the User-based
Security Model.
"
INDEX { usmUserEngineID,
usmUserName
}
::= { usmUserTable 1 }
UsmUserEntry ::= SEQUENCE
{
usmUserEngineID SnmpEngineID,
usmUserName SnmpAdminString,
usmUserSecurityName SnmpAdminString,
usmUserCloneFrom RowPointer,
usmUserAuthProtocol AutonomousType,
usmUserAuthKeyChange KeyChange,
usmUserOwnAuthKeyChange KeyChange,
usmUserPrivProtocol AutonomousType,
usmUserPrivKeyChange KeyChange,
usmUserOwnPrivKeyChange KeyChange,
usmUserPublic OCTET STRING,
usmUserStorageType StorageType,
usmUserStatus RowStatus
}
usmUserEngineID OBJECT-TYPE
SYNTAX SnmpEngineID
MAX-ACCESS not-accessible
STATUS current
DESCRIPTION "An SNMP engine's administratively-unique identifier.
In a simple agent, this value is always that agent's
own snmpEngineID value.
The value can also take the value of the snmpEngineID
of a remote SNMP engine with which this user can
communicate.
"
::= { usmUserEntry 1 }
usmUserName OBJECT-TYPE
SYNTAX SnmpAdminString (SIZE(1..32))
MAX-ACCESS not-accessible
STATUS current
DESCRIPTION "A human readable string representing the name of
the user.
This is the (User-based Security) Model dependent
security ID.
"
::= { usmUserEntry 2 }
usmUserSecurityName OBJECT-TYPE
SYNTAX SnmpAdminString
MAX-ACCESS read-only
STATUS current
DESCRIPTION "A human readable string representing the user in
Security Model independent format.
The default transformation of the User-based Security
Model dependent security ID to the securityName and
vice versa is the identity function so that the
securityName is the same as the userName.
"
::= { usmUserEntry 3 }
usmUserCloneFrom OBJECT-TYPE
SYNTAX RowPointer
MAX-ACCESS read-create
STATUS current
DESCRIPTION "A pointer to another conceptual row in this
usmUserTable. The user in this other conceptual
row is called the clone-from user.
When a new user is created (i.e., a new conceptual
row is instantiated in this table), the privacy and
authentication parameters of the new user must be
cloned from its clone-from user. These parameters are:
- authentication protocol (usmUserAuthProtocol)
- privacy protocol (usmUserPrivProtocol)
They will be copied regardless of what the current
value is.
Cloning also causes the initial values of the secret
authentication key (authKey) and the secret encryption
key (privKey) of the new user to be set to the same
values as the corresponding secrets of the clone-from
user to allow the KeyChange process to occur as
required during user creation.
The first time an instance of this object is set by
a management operation (either at or after its
instantiation), the cloning process is invoked.
Subsequent writes are successful but invoke no
action to be taken by the receiver.
The cloning process fails with an 'inconsistentName'
error if the conceptual row representing the
clone-from user does not exist or is not in an active
state when the cloning process is invoked.
When this object is read, the ZeroDotZero OID
is returned.
"
::= { usmUserEntry 4 }
usmUserAuthProtocol OBJECT-TYPE
SYNTAX AutonomousType
MAX-ACCESS read-create
STATUS current
DESCRIPTION "An indication of whether messages sent on behalf of
this user to/from the SNMP engine identified by
usmUserEngineID, can be authenticated, and if so,
the type of authentication protocol which is used.
An instance of this object is created concurrently
with the creation of any other object instance for
the same user (i.e., as part of the processing of
the set operation which creates the first object
instance in the same conceptual row).
If an initial set operation (i.e. at row creation time)
tries to set a value for an unknown or unsupported
protocol, then a 'wrongValue' error must be returned.
The value will be overwritten/set when a set operation
is performed on the corresponding instance of
usmUserCloneFrom.
Once instantiated, the value of such an instance of
this object can only be changed via a set operation to
the value of the usmNoAuthProtocol.
If a set operation tries to change the value of an
existing instance of this object to any value other
than usmNoAuthProtocol, then an 'inconsistentValue'
error must be returned.
If a set operation tries to set the value to the
usmNoAuthProtocol while the usmUserPrivProtocol value
in the same row is not equal to usmNoPrivProtocol,
then an 'inconsistentValue' error must be returned.
That means that an SNMP command generator application
must first ensure that the usmUserPrivProtocol is set
to the usmNoPrivProtocol value before it can set
the usmUserAuthProtocol value to usmNoAuthProtocol.
"
DEFVAL { usmNoAuthProtocol }
::= { usmUserEntry 5 }
usmUserAuthKeyChange OBJECT-TYPE
SYNTAX KeyChange -- typically (SIZE (0 | 32)) for HMACMD5
-- typically (SIZE (0 | 40)) for HMACSHA
MAX-ACCESS read-create
STATUS current
DESCRIPTION "An object, which when modified, causes the secret
authentication key used for messages sent on behalf
of this user to/from the SNMP engine identified by
usmUserEngineID, to be modified via a one-way
function.
The associated protocol is the usmUserAuthProtocol.
The associated secret key is the user's secret
authentication key (authKey). The associated hash
algorithm is the algorithm used by the user's
usmUserAuthProtocol.
When creating a new user, it is an 'inconsistentName'
error for a set operation to refer to this object
unless it is previously or concurrently initialized
through a set operation on the corresponding instance
of usmUserCloneFrom.
When the value of the corresponding usmUserAuthProtocol
is usmNoAuthProtocol, then a set is successful, but
effectively is a no-op.
When this object is read, the zero-length (empty)
string is returned.
The recommended way to do a key change is as follows:
1) GET(usmUserSpinLock.0) and save in sValue.
2) generate the keyChange value based on the old
(existing) secret key and the new secret key,
let us call this kcValue.
If you do the key change on behalf of another user:
3) SET(usmUserSpinLock.0=sValue,
usmUserAuthKeyChange=kcValue
usmUserPublic=randomValue)
If you do the key change for yourself:
4) SET(usmUserSpinLock.0=sValue,
usmUserOwnAuthKeyChange=kcValue
usmUserPublic=randomValue)
If you get a response with error-status of noError,
then the SET succeeded and the new key is active.
If you do not get a response, then you can issue a
GET(usmUserPublic) and check if the value is equal
to the randomValue you did send in the SET. If so, then
the key change succeeded and the new key is active
(probably the response got lost). If not, then the SET
request probably never reached the target and so you
can start over with the procedure above.
"
DEFVAL { ''H } -- the empty string
::= { usmUserEntry 6 }
usmUserOwnAuthKeyChange OBJECT-TYPE
SYNTAX KeyChange -- typically (SIZE (0 | 32)) for HMACMD5
-- typically (SIZE (0 | 40)) for HMACSHA
MAX-ACCESS read-create
STATUS current
DESCRIPTION "Behaves exactly as usmUserAuthKeyChange, with one
notable difference: in order for the set operation
to succeed, the usmUserName of the operation
requester must match the usmUserName that
indexes the row which is targeted by this
operation.
In addition, the USM security model must be
used for this operation.
The idea here is that access to this column can be
public, since it will only allow a user to change
his own secret authentication key (authKey).
Note that this can only be done once the row is active.
When a set is received and the usmUserName of the
requester is not the same as the umsUserName that
indexes the row which is targeted by this operation,
then a 'noAccess' error must be returned.
When a set is received and the security model in use
is not USM, then a 'noAccess' error must be returned.
"
DEFVAL { ''H } -- the empty string
::= { usmUserEntry 7 }
usmUserPrivProtocol OBJECT-TYPE
SYNTAX AutonomousType
MAX-ACCESS read-create
STATUS current
DESCRIPTION "An indication of whether messages sent on behalf of
this user to/from the SNMP engine identified by
usmUserEngineID, can be protected from disclosure,
and if so, the type of privacy protocol which is used.
An instance of this object is created concurrently
with the creation of any other object instance for
the same user (i.e., as part of the processing of
the set operation which creates the first object
instance in the same conceptual row).
If an initial set operation (i.e. at row creation time)
tries to set a value for an unknown or unsupported
protocol, then a 'wrongValue' error must be returned.
The value will be overwritten/set when a set operation
is performed on the corresponding instance of
usmUserCloneFrom.
Once instantiated, the value of such an instance of
this object can only be changed via a set operation to
the value of the usmNoPrivProtocol.
If a set operation tries to change the value of an
existing instance of this object to any value other
than usmNoPrivProtocol, then an 'inconsistentValue'
error must be returned.
Note that if any privacy protocol is used, then you
must also use an authentication protocol. In other
words, if usmUserPrivProtocol is set to anything else
than usmNoPrivProtocol, then the corresponding instance
of usmUserAuthProtocol cannot have a value of
usmNoAuthProtocol. If it does, then an
'inconsistentValue' error must be returned.
"
DEFVAL { usmNoPrivProtocol }
::= { usmUserEntry 8 }
usmUserPrivKeyChange OBJECT-TYPE
SYNTAX KeyChange -- typically (SIZE (0 | 32)) for DES
MAX-ACCESS read-create
STATUS current
DESCRIPTION "An object, which when modified, causes the secret
encryption key used for messages sent on behalf
of this user to/from the SNMP engine identified by
usmUserEngineID, to be modified via a one-way
function.
The associated protocol is the usmUserPrivProtocol.
The associated secret key is the user's secret
privacy key (privKey). The associated hash
algorithm is the algorithm used by the user's
usmUserAuthProtocol.
When creating a new user, it is an 'inconsistentName'
error for a set operation to refer to this object
unless it is previously or concurrently initialized
through a set operation on the corresponding instance
of usmUserCloneFrom.
When the value of the corresponding usmUserPrivProtocol
is usmNoPrivProtocol, then a set is successful, but
effectively is a no-op.
When this object is read, the zero-length (empty)
string is returned.
See the description clause of usmUserAuthKeyChange for
a recommended procedure to do a key change.
"
DEFVAL { ''H } -- the empty string
::= { usmUserEntry 9 }
usmUserOwnPrivKeyChange OBJECT-TYPE
SYNTAX KeyChange -- typically (SIZE (0 | 32)) for DES
MAX-ACCESS read-create
STATUS current
DESCRIPTION "Behaves exactly as usmUserPrivKeyChange, with one
notable difference: in order for the Set operation
to succeed, the usmUserName of the operation
requester must match the usmUserName that indexes
the row which is targeted by this operation.
In addition, the USM security model must be
used for this operation.
The idea here is that access to this column can be
public, since it will only allow a user to change
his own secret privacy key (privKey).
Note that this can only be done once the row is active.
When a set is received and the usmUserName of the
requester is not the same as the umsUserName that
indexes the row which is targeted by this operation,
then a 'noAccess' error must be returned.
When a set is received and the security model in use
is not USM, then a 'noAccess' error must be returned.
"
DEFVAL { ''H } -- the empty string
::= { usmUserEntry 10 }
usmUserPublic OBJECT-TYPE
SYNTAX OCTET STRING (SIZE(0..32))
MAX-ACCESS read-create
STATUS current
DESCRIPTION "A publicly-readable value which can be written as part
of the procedure for changing a user's secret
authentication and/or privacy key, and later read to
determine whether the change of the secret was
effected.
"
DEFVAL { ''H } -- the empty string
::= { usmUserEntry 11 }
usmUserStorageType OBJECT-TYPE
SYNTAX StorageType
MAX-ACCESS read-create
STATUS current
DESCRIPTION "The storage type for this conceptual row.
Conceptual rows having the value 'permanent' must
allow write-access at a minimum to:
- usmUserAuthKeyChange, usmUserOwnAuthKeyChange
and usmUserPublic for a user who employs
authentication, and
- usmUserPrivKeyChange, usmUserOwnPrivKeyChange
and usmUserPublic for a user who employs
privacy.
Note that any user who employs authentication or
privacy must allow its secret(s) to be updated and
thus cannot be 'readOnly'.
If an initial set operation tries to set the value to
'readOnly' for a user who employs authentication or
privacy, then an 'inconsistentValue' error must be
returned. Note that if the value has been previously
set (implicit or explicit) to any value, then the rules
as defined in the StorageType Textual Convention apply.
It is an implementation issue to decide if a SET for
a readOnly or permanent row is accepted at all. In some
contexts this may make sense, in others it may not. If
a SET for a readOnly or permanent row is not accepted
at all, then a 'wrongValue' error must be returned.
"
DEFVAL { nonVolatile }
::= { usmUserEntry 12 }
usmUserStatus OBJECT-TYPE
SYNTAX RowStatus
MAX-ACCESS read-create
STATUS current
DESCRIPTION "The status of this conceptual row.
Until instances of all corresponding columns are
appropriately configured, the value of the
corresponding instance of the usmUserStatus column
is 'notReady'.
In particular, a newly created row for a user who
employs authentication, cannot be made active until the
corresponding usmUserCloneFrom and usmUserAuthKeyChange
have been set.
Further, a newly created row for a user who also
employs privacy, cannot be made active until the
usmUserPrivKeyChange has been set.
The RowStatus TC [RFC2579] requires that this
DESCRIPTION clause states under which circumstances
other objects in this row can be modified:
The value of this object has no effect on whether
other objects in this conceptual row can be modified,
except for usmUserOwnAuthKeyChange and
usmUserOwnPrivKeyChange. For these 2 objects, the
value of usmUserStatus MUST be active.
"
::= { usmUserEntry 13 }
-- Conformance Information *******************************************
usmMIBCompliances OBJECT IDENTIFIER ::= { usmMIBConformance 1 }
usmMIBGroups OBJECT IDENTIFIER ::= { usmMIBConformance 2 }
-- Compliance statements
usmMIBCompliance MODULE-COMPLIANCE
STATUS current
DESCRIPTION "The compliance statement for SNMP engines which
implement the SNMP-USER-BASED-SM-MIB.
"
MODULE -- this module
MANDATORY-GROUPS { usmMIBBasicGroup }
OBJECT usmUserAuthProtocol
MIN-ACCESS read-only
DESCRIPTION "Write access is not required."
OBJECT usmUserPrivProtocol
MIN-ACCESS read-only
DESCRIPTION "Write access is not required."
::= { usmMIBCompliances 1 }
-- Units of compliance
usmMIBBasicGroup OBJECT-GROUP
OBJECTS {
usmStatsUnsupportedSecLevels,
usmStatsNotInTimeWindows,
usmStatsUnknownUserNames,
usmStatsUnknownEngineIDs,
usmStatsWrongDigests,
usmStatsDecryptionErrors,
usmUserSpinLock,
usmUserSecurityName,
usmUserCloneFrom,
usmUserAuthProtocol,
usmUserAuthKeyChange,
usmUserOwnAuthKeyChange,
usmUserPrivProtocol,
usmUserPrivKeyChange,
usmUserOwnPrivKeyChange,
usmUserPublic,
usmUserStorageType,
usmUserStatus
}
STATUS current
DESCRIPTION "A collection of objects providing for configuration
of an SNMP engine which implements the SNMP
User-based Security Model.
"
::= { usmMIBGroups 1 }
END
6.安全机制
HMAC-MD5
HMAC-MD5-96 Authentication Protocol是一种基于HMAC和MD5算法的认证协议,它用于确保数据包的来源和完整性。以下是其实现的基本原理:
-
密钥选择:HMAC-MD5-96认证协议假设认证密钥的选择由调用者完成,并且调用者将要使用的密钥传递给认证模块。这个密钥的长度必须为16个八进制数。
-
消息处理:HMAC-MD5-96认证协议处理接收到的SNMP消息。具体的处理过程包括:生成消息认证码(MAC),验证消息的完整性和来源,以及处理可能的错误。
-
消息认证:HMAC-MD5-96认证协议使用MD5算法生成一个128位的认证值。这个128位的值可以被截断,但是至少需要保留96位,以满足安全要求。
-
消息发送和接收:在发送消息时,将截断的认证值存储在认证字段中。在接收消息时,计算整个128位的认证值,并将其与存储在认证字段中的值进行比较。如果两者相同,则认证成功2。
-
密钥管理:HMAC-MD5-96认证协议是一种密钥算法。为了提供数据来源认证,密钥分发机制必须确保分配了唯一的密钥,并且只将它们分发给参与通信的方。
-
安全考虑:HMAC-MD5-96认证协议的安全性基于HMAC的强度,以及MD5的一定程度的强度。虽然MD5在最初被认为具有很强的碰撞抵抗性,但是最近的研究发现它实际上并不具有很强的碰撞抵抗性。因此,对于HMAC-MD5-96认证协议的安全性评估,需要考虑MD5的这个特性。
HMAC-SHA1
HMAC-SHA-96 Authentication Protocol是一种基于HMAC和SHA算法的认证协议,它用于确保数据包的来源和完整性。以下是其实现的基本原理:
-
密钥选择:HMAC-SHA-96认证协议假设认证密钥的选择由调用者完成,并且调用者将要使用的密钥传递给认证模块。这个密钥的长度必须为20个八进制数。
-
消息处理:HMAC-SHA-96认证协议处理接收到的SNMP消息。具体的处理过程包括:生成消息认证码(MAC),验证消息的完整性和来源,以及处理可能的错误。
-
消息认证:HMAC-SHA-96认证协议使用SHA算法生成一个160位的认证值。这个160位的值可以被截断,但是至少需要保留96位,以满足安全要求。
-
消息发送和接收:在发送消息时,将截断的认证值存储在认证字段中。在接收消息时,计算整个160位的认证值,并将其与存储在认证字段中的值进行比较。如果两者相同,则认证成功。。
-
密钥管理:HMAC-SHA-96认证协议是一种密钥算法。为了提供数据来源认证,密钥分发机制必须确保分配了唯一的密钥,并且只将它们分发给参与通信的方。
-
安全考虑:HMAC-SHA-96认证协议的安全性基于HMAC的强度,以及SHA的一定程度的强度。虽然SHA在最初被认为具有很强的碰撞抵抗性,但是最近的研究发现它实际上并不具有很强的碰撞抵抗性。因此,对于HMAC-SHA-96认证协议的安全性评估,需要考虑SHA的这个特性。
CBC-DES
CBC-DES Symmetric Encryption Protocol是RFC3414中定义的一种用户基础安全模型的第一种隐私协议。这个协议使用DES(数据加密标准)进行对称加密,以确保数据的机密性。以下是其工作流程的详细描述:
-
选择加密算法:为了支持数据机密性,需要一个加密算法。适当的消息部分在传输之前需要被加密。用户基础安全模型规定,需要加密的部分是scopedPDU。
-
创建加密和解密密钥:一个秘密值和一个时效值被用来创建加密和解密密钥以及初始化向量。这个秘密值被所有被授权在代表适当用户的名义发送消息的SNMP引擎共享。
-
对称加密协议:这个协议提供了对数据机密性的支持。被指定的SNMP消息部分被加密并作为发送给接收者的消息的一部分包含在内。
-
DES密钥和初始化向量:DES密钥和初始化向量的生成方法在RFC3414中有详细的描述。这个过程涉及到秘密值、时效值和用户的私钥。
-
数据加密:指定的SNMP消息部分被加密并作为发送给接收者的消息的一部分包含在内。
-
数据解密:在接收消息时,使用相同的DES密钥和初始化向量对接收到的加密数据进行解密。