SNMPv3 -- View Access Control Model
Eric Davis
This is the second of two articles presenting the new security features defined by SNMPv3. In the previous article (Sys Admin, May 2000), I covered the User-based Security Model (USM) and how it authenticated, encrypted, and decrypted SNMPv3 packets. Now I'll examine the View-based Access Control Model (VACM) that provides access control and is specified in RFC 2575.
The Access Control Subsystem of an SNMP entity has the responsibility for checking whether a specific type of access to a specific managed object is allowed. Access control occurs in the agent when processing SNMP retrieval or modification request messages from a manager, and also when a notification message must be sent to the manager.
The concepts introduced by the VACM are rather complex and confusing, but I hope I can clarify them. The motivations for these concepts are based on the problems with the SNMPv1 and SNMPv2c community string. The community string is used to identify the requesting entity, the location of the requesting entity, determine access control information, and determine MIB view information. Both flexibility and functionality are lost by using this single community string variable. The VACM elaborates on the community string concept by allowing a much stricter and more dynamic access control model that is easy to administer. Figure 1 shows the SNMPv3 Packet Format.
The SNMP packet structure for version 3 has been changed to accommodate the use of a security model like the USM and an access control model like the VACM.
msgVersion -- The SNMP version of the packet (e.g., 1, 2, or 3).
msgID -- The msgID is used to coordinate request and response messages between manager and agent. A msgID in a response must be the same as the msgID received in the request.
msgMaxSize -- The msgMaxSize conveys the maximum message size the sender is able to accept from another SNMP engine.
msgFlags -- The msgFlags is a single octet that is used to convey how the message is to be processed. For instance, two bits of the msgFlags are used to specify whether or not the packet has been authenticated and whether or not it has been encrypted.
msgSecurityModel -- SNMPv3 was designed for the use of multiple co-existing security models. The msgSecurityModel field specifies the security model that was used to generate the message. Therefore, the receiving entity knows which security model must be used to perform security processing upon message reception.
msgSecurityParameters -- The msgSecurityParameters is an octet string that contains the security model specific data. This data is defined by and used only by the security model specified by the msgSecurityModel. I illustrated in the previous article how the USM used this field for authenticating, encrypting, and decrypting SNMPv3 messages.
scopedPDU -- The scopedPDU contains the normal PDU and information for identifying the administratively unique context for processing the PDU.
VACM Parameters The VACM uses the msgFlags, msgSecurityModel, and scopedPDU field for determining message access. The msgFlags are used to determine the security level of the message (i.e., noAuthNoPriv, authNoPriv, or authPriv). The msgSecurityModel specifies the security model used to secure the message and the scopedPDU contains the context and managed object OIDs. The scopedPDU contains the following fields:
contextEngineID -- The contextEngineID uniquely identifies an SNMP entity that may access an instance of a managed object within a particular context.
contextName -- The unique name of the context for which the PDU data administratively belongs.
PDU (data) -- An SNMP Protocol Data Unit contains an operation for information that is named in the context that is identified within an administrative domain by the combination of the contextEngineID and the contextName. See RFC1905 for more information about SNMP PDUs.
All of these parameters are passed to the isAccessAllowed mechanism. This is the single entry point into the VACM for determining whether or not access is granted to the message. Every var-bind in the PDU is individually checked for access. If it is determined that one of the var-binds (i.e., managed objects) is inaccessible to the message, then an error is returned to the caller and processing stops. There are four tables defined by the VACM that are used for determining access. Each table is responsible for a different aspect of the access mechanism, and each of these tables is remotely configurable using the VACM MIB.
The algorithm defined by the VACM for determining access is somewhat complex and hard to understand. Figure 2 is a flow chart that shows the inputs and outputs to each of the four tables which will be described in the following sections. The RFC gives the example that the securityModel and securityName determine Who. The contextName determines Where. The securityModel and securityLevel determine How. The viewType (i.e., read, write, or notify) determines Why. The OID of the managed object determines What, and the instances of the managed object determine Which.
Context Table A context is defined as a collection of managed objects accessible by an SNMP entity. In other words, a name is given to a subset of managed objects. It is possible for an object to exist in more than one context, and it is possible that an SNMP entity has access to more than one context. The vacmContextTable is used to store all the locally available contexts. The table is indexed by a contextName, and each row in this table contains vacmContextName -- a unique human readable string that names a context.
The contextName found within the scopedPDU is searched for in the vacmContextTable. If the message's specified contextName is not found in the table, access is denied and noSuchContext is returned. Otherwise, access checking continues if the contextName exists.
Security to Group Table A group name is used to define an access control policy for a group of principals. Note that a principal is more specific than an SNMP entity. It is more like an individual user operating from an SNMP entity. A group is a set of zero or more securityModel and securityName tuples on whose behalf managed objects can be accessed. The combination of a securityModel and a securityName maps to, at most, one group. That is, a given principal whose communications are protected by a given securityModel can only be included in one group. The vacmSecurityToGroupTable is used to store group information and is indexed by a securityModel and securityName. Each row in this table contains:
vacmSecurityModel -- An SNMPv3 security model (i.e., USM).
vacmSecurityName -- A name representing a principal in a security model independent format. In the case of the USM, this securityName is identical to the userName.
vacmGroupName -- A human readable string that identifies the group to which this table entry belongs.
The securityName used to index into this table is retrieved by the msgSecurityModel when the message is processed (i.e., authenticated and decrypted). Then the securityName and msgSecurityModel tuple is searched for in the table. If an entry is not found, access is denied and noSuchGroupName is returned. Or, if an entry is found, the corresponding groupName is returned and access checking continues.
Access Table The vacmAccessTable is used to store the access rights defined for groups. In determining whether access is allowed, one entry must be selected and the proper viewName from that entry must be used for further access checking. There may be multiple access rights defined for a single group, and the access right chosen from that set is determined by which is the most secure. This means that the entry with the highest security model or with the longest context prefix match is chosen. See the vacmAccessTable MIB description for the details of the algorithm. This table is indexed by a groupName, contextPrefix, securityModel, and securityLevel. Each row in this table contains:
vacmGroupName -- The name of the group to which this access right applies.
vacmAccessContextMatch -- A simple form of wildcarding. If set to exact, the index contextName must exactly match the value in vacmAccessContextPrefix. If set to prefix, the index contextName can simply match the first few starting characters of the value in vacmAccessContextPrefix.
vacmAccessContextPrefix -- An index contextName must match exactly or partially the value of this object.
vacmAccessSecurityModel -- The securityModel that must be used in order to gain access to this access right.
vacmAccessSecurityLevel -- The minimum securityLevel that must be used in order to gain access to this access right. A security level of noAuthNoPriv is less than authNoPriv and authNoPriv is less than authPriv.
vacmAccessReadViewName -- The authorized MIB viewName used for read access. If the value is the empty string, then there is no active view configured for read access.
vacmAccessWriteViewName -- The authorized MIB viewName used for write access. If the value is the empty string, then there is no active view configured for write access.
vacmAccessNotifyViewName -- The authorized MIB viewName used for notify access. If the value is the empty string, then there is no active view configured for notify access.
The contextName used when indexing this table is the valid contextName that was already matched within the vacmContextTable. The groupName used is the one returned from the lookup into the vacmSecurityToGroupTable. The securityModel is specified in the message's msgSecurityModel, and the securityLevel is specified in the msgFlags. If an access right was not found, access is denied and noAccessEntry is returned.
Once an access right has been chosen, the appropriate viewName specified by the access right must be chosen. The view name to use is determined by the SNMP operation defined in the PDU. For GET and NEXT operations, the vacmAccessReadViewName is used. For SET operations, the vacmAccessWriteViewName is used. For TRAP operations, the vacmAccessNotifyViewName is used. If the appropriate viewName is not configured within the access right, access is denied and noSuchView is returned. Finally, if the access right has been chosen and the appropriate viewName has been configured within the access right, access checking continues.
View Tree Family Table The vacmViewTreeFamilyTable is used to store MIB views. A MIB view is defined as a family of view subtrees that is a pairing of an OID subtree value together with a bit-string mask value. The mask indicates which sub-identifiers of the associated subtree OID are significant to the MIB view's definition.
For each possible managed object instance, that instance belongs to a particular MIB view if both of the following conditions are true:
The OID of the managed object must contain at least as many sub-identifiers as the OID subtree.
Each sub-identifier in the OID of the managed object matches the corresponding sub-identifier of the OID subtree whenever the corresponding bit of the mask is non-zero.
When the configured value of the mask is shorter than required to perform the above test, its value is implicitly extended with ones. Consequently, a view subtree family having a family mask of zero length always corresponds to a mask of all ones, which in turn corresponds to a single MIB subtree. For example, suppose the following MIB views have been defined:
(A) subtree: 1.3.6.1.2.1
mask: 1 1 1 1 1 1
(B) subtree: 1.3.6.1.2.1.1.1
mask: 1 1 1
(C) subtree: 1.3.6.1.2.1.2
mask: none
(D) subtree: 1.3.6.1.2.1.1
mask: 1 1 0 1 0 1 1
(E) subtree: 1.3.6.1.2.1.2
mask: 1 1 0 1 0
(F) subtree: 1.3.6.1.2.1
mask: 1 1 0 1 0 1
Here are some OIDs that are checked against the above MIB views to determine whether they are a part of the view. You can see that by using a subtree mask, a managed object can be included in multiple MIB views or no MIB views.
1.3.6.1.2.1 belongs to: A, F
1.2.6.1.2.1.1 belongs to: none of them
1.3.6.1.3.1 belongs to: F
1.3.4.1.4.1.2 belongs to: E, F
1.3.6.1.2.1.1.1.0 belongs to: A, B, D, F
1.3.6.1.2 belongs to: none of them
All the MIB views are stored in the vacmViewTreeFamilyTable which is indexed by a viewName and an OID of a MIB subtree. Note that the VACM MIB defines the vacmViewSpinLock advisory lock that is used to allow several SNMP managers to coordinate their attempts in modifying the table. The use of this spin lock is identical to that of the USM's usmUserSpinLock explained in the previous article. Each row in the vacmViewTreeFamilyTable contains:
vacmViewTreeFamilyViewName -- A human readable name for the MIB view.
vacmViewTreeFamilySubtree -- The OID subtree that, when combined with the mask, defines one or more MIB view subtrees.
vacmViewTreeFamilyMask -- A bit mask that, in combination with the corresponding OID subtree, defines one or more MIB view subtrees.
vacmViewTreeFamilyType -- Indicates whether the corresponding MIB view subtrees defined by the OID subtree and mask are included or excluded from the MIB view.
The viewName used to index into this table for access checking is the authorized viewName specified by the access right chosen from the vacmAccessTable. The OID of a managed object found in each var-bind of the PDU is checked against the MIB view. If the OID is not a part of the MIB view, access is denied and notInView is returned. If the OID is a part of the MIB view, then access has been granted and accessAllowed is returned.
Conclusion This overview of the VACM should give you an understanding of what is involved in administering access control for SNMPv3 packets. Additionally, you can start to think about how you will configure the agents in your environment when you deploy SNMPv3 capable routers, switches, and servers.
Take care when configuring each of the VACM tables. A minor misconfiguration can open a huge security hole in your network by allowing unauthorized access to potentially sensitive data. Try to test your table configurations first on a test network before making any modifications to a live network device.
The SNMPv3 framework is defined to ensure the modularity of the security subsystem and the access control subsystem. As of right now, the USM and VACM have been defined for security and access control. There is nothing stopping you from implementing either a new security module or access control model or both. In the future, expect to see the IETF update or replace these modules as they become outdated and needs change. In any case, given the modularity of the SNMPv3 framework, defining and plugging in a new module will be quite painless.
References SNMPv3: RFCs 2570, 2571, 2572, 2573, 2574, 2575
Stallings, William, SNMP, SNMPv2, SNMPv3, and RMON 1 and 2 (Third Edition). Addison-Wesley Publishing Company.
Perkins, David, and Evan McGinnis. 1996. Understanding SNMP MIBs. Prentice Hall.
About the Author
Eric Davis is a Software Engineer in the networking division of Wind River Systems. There he works on the TCP/IP stack of the VxWorks embedded OS. He lives in the SF Bay Area with his wife Kathie and dog Maka. He can be reached at: edavis@windriver.com.
|