# # This file is part of pysnmp software. # # Copyright (c) 2005-2016, Ilya Etingof # License: http://pysnmp.sf.net/license.html # from pysnmp.smi.error import NoSuchInstanceError from pysnmp.proto import errind, error from pysnmp import debug __powOfTwoSeq = [128, 64, 32, 16, 8, 4, 2, 1] # 3.2 class Vacm: """View-based Access Control Model""" accessModelID = 3 def isAccessAllowed(self, snmpEngine, securityModel, securityName, securityLevel, viewType, contextName, variableName): mibInstrumController = snmpEngine.msgAndPduDsp.mibInstrumController debug.logger & debug.flagACL and debug.logger('isAccessAllowed: securityModel %s, securityName %s, securityLevel %s, viewType %s, contextName %s for variableName %s' % (securityModel, securityName, securityLevel, viewType, contextName, variableName)) # 3.2.1 vacmContextEntry, = mibInstrumController.mibBuilder.importSymbols('SNMP-VIEW-BASED-ACM-MIB', 'vacmContextEntry') tblIdx = vacmContextEntry.getInstIdFromIndices(contextName) try: vacmContextName = vacmContextEntry.getNode( vacmContextEntry.name + (1,) + tblIdx ).syntax except NoSuchInstanceError: raise error.StatusInformation(errorIndication=errind.noSuchContext) # 3.2.2 vacmSecurityToGroupEntry, = mibInstrumController.mibBuilder.importSymbols('SNMP-VIEW-BASED-ACM-MIB', 'vacmSecurityToGroupEntry') tblIdx = vacmSecurityToGroupEntry.getInstIdFromIndices( securityModel, securityName ) try: vacmGroupName = vacmSecurityToGroupEntry.getNode( vacmSecurityToGroupEntry.name + (3,) + tblIdx ).syntax except NoSuchInstanceError: raise error.StatusInformation(errorIndication=errind.noGroupName) # 3.2.3 vacmAccessEntry, = mibInstrumController.mibBuilder.importSymbols( 'SNMP-VIEW-BASED-ACM-MIB', 'vacmAccessEntry' ) # XXX partial context name match tblIdx = vacmAccessEntry.getInstIdFromIndices( vacmGroupName, contextName, securityModel, securityLevel ) # 3.2.4 if viewType == 'read': entryIdx = vacmAccessEntry.name + (5,) + tblIdx elif viewType == 'write': entryIdx = vacmAccessEntry.name + (6,) + tblIdx elif viewType == 'notify': entryIdx = vacmAccessEntry.name + (7,) + tblIdx else: raise error.ProtocolError('Unknown view type %s' % viewType) try: viewName = vacmAccessEntry.getNode(entryIdx).syntax except NoSuchInstanceError: raise error.StatusInformation(errorIndication=errind.noAccessEntry) if not len(viewName): raise error.StatusInformation(errorIndication=errind.noSuchView) # XXX split onto object & instance ? # 3.2.5a vacmViewTreeFamilyEntry, = mibInstrumController.mibBuilder.importSymbols('SNMP-VIEW-BASED-ACM-MIB', 'vacmViewTreeFamilyEntry') tblIdx = vacmViewTreeFamilyEntry.getInstIdFromIndices(viewName) # Walk over entries initialTreeName = treeName = vacmViewTreeFamilyEntry.name + (2,) + tblIdx maskName = vacmViewTreeFamilyEntry.name + (3,) + tblIdx while 1: vacmViewTreeFamilySubtree = vacmViewTreeFamilyEntry.getNextNode( treeName ) vacmViewTreeFamilyMask = vacmViewTreeFamilyEntry.getNextNode( maskName ) treeName = vacmViewTreeFamilySubtree.name maskName = vacmViewTreeFamilyMask.name if initialTreeName != treeName[:len(initialTreeName)]: # 3.2.5b raise error.StatusInformation(errorIndication=errind.notInView) l = len(vacmViewTreeFamilySubtree.syntax) if l > len(variableName): continue if vacmViewTreeFamilyMask.syntax: mask = [] for c in vacmViewTreeFamilyMask.syntax.asNumbers(): mask = mask + [b&c for b in __powOfTwoSeq] m = len(mask)-1 idx = l-1 while idx: if idx > m or mask[idx] and \ vacmViewTreeFamilySubtree.syntax[idx] != variableName[idx]: break idx = idx - 1 if idx: continue # no match else: # no mask if vacmViewTreeFamilySubtree.syntax != variableName[:l]: continue # no match # 3.2.5c return error.StatusInformation(errorIndication=errind.accessAllowed)