All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.snmp4j.agent.mo.snmp.VacmMIB Maven / Gradle / Ivy

/*_############################################################################
  _## 
  _##  SNMP4J-Agent - VacmMIB.java  
  _## 
  _##  Copyright (C) 2005-2009  Frank Fock (SNMP4J.org)
  _##  
  _##  Licensed under the Apache License, Version 2.0 (the "License");
  _##  you may not use this file except in compliance with the License.
  _##  You may obtain a copy of the License at
  _##  
  _##      http://www.apache.org/licenses/LICENSE-2.0
  _##  
  _##  Unless required by applicable law or agreed to in writing, software
  _##  distributed under the License is distributed on an "AS IS" BASIS,
  _##  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  _##  See the License for the specific language governing permissions and
  _##  limitations under the License.
  _##  
  _##########################################################################*/


package org.snmp4j.agent.mo.snmp;

import java.util.*;

import org.snmp4j.log.*;
import org.snmp4j.agent.*;
import org.snmp4j.agent.mo.*;
import org.snmp4j.agent.mo.util.*;
import org.snmp4j.agent.security.*;
import org.snmp4j.security.*;
import org.snmp4j.smi.*;

/**
 * This concrete implementation of the SNMP-VIEW-BASED-ACM-MIB (RFC 3415).
 * The configuration of the view access model can be changed programatically
 * (see {@link MutableVACM}) or via SNMP but an initial configuration must be
 * created programatically in order to allow any access to the agent via SNMP.
 *
 * @author Frank Fock
 * @version 1.0
 */
public class VacmMIB implements MOGroup, MutableVACM {

  private static final LogAdapter logger = LogFactory.getLogger(VacmMIB.class);

  public static final OID vacmContextEntryOID =
      new OID(new int[] {1,3,6,1,6,3,16,1,1,1});

  public static final int colVacmGroupName = 3;
  public static final int colVacmSecurityToGroupStorageType = 4;
  public static final int colVacmSecurityToGroupRowStatus = 5;

  public static final int idxVacmGroupName = 0;
  public static final int idxVacmSecurityToGroupStorageType = 1;
  public static final int idxVacmSecurityToGroupRowStatus = 2;

  public static final OID vacmSecurityToGroupEntryOID =
      new OID(new int[] {1,3,6,1,6,3,16,1,2,1});

  public static final int colVacmAccessContextMatch = 4;
  public static final int colVacmAccessReadViewName = 5;
  public static final int colVacmAccessWriteViewName = 6;
  public static final int colVacmAccessNotifyViewName = 7;
  public static final int colVacmAccessStorageType = 8;
  public static final int colVacmAccessRowStatus = 9;

//  private static final int idxVacmAccessGroupName = 0;
  public static final int idxVacmAccessContextPrefix = 1;
  public static final int idxVacmAccessSecurityModel = 2;
  public static final int idxVacmAccessSecurityLevel = 3;
  public static final int idxVacmAccessContextMatch = 0;
  public static final int idxVacmAccessReadViewName = 1;
  public static final int idxVacmAccessWriteViewName = 2;
  public static final int idxVacmAccessNotifyViewName = 3;
  public static final int idxVacmAccessStorageType = 4;
  public static final int idxVacmAccessRowStatus = 5;

  public static final OID vacmAccessEntryOID =
      new OID(new int[] {1,3,6,1,6,3,16,1,4,1});

  public static final int vacmExactMatch = MutableVACM.VACM_MATCH_EXACT;
  public static final int vacmPrefixMatch = MutableVACM.VACM_MATCH_PREFIX;


  public static final OID vacmViewSpinLockOID =
      new OID(new int[] {1,3,6,1,6,3,16,1,5,1,0});

  public static final int colVacmViewTreeFamilyMask = 3;
  public static final int colVacmViewTreeFamilyType = 4;
  public static final int colVacmViewTreeFamilyStorageType = 5;
  public static final int colVacmViewTreeFamilyRowStatus = 6;

//  private static final int idxVacmViewTreeViewName = 0;
  public static final int idxVacmViewTreeSubtree = 1;

  public static final int idxVacmViewTreeFamilyMask = 0;
  public static final int idxVacmViewTreeFamilyType = 1;
  public static final int idxVacmViewTreeFamilyStorageType = 2;
  public static final int idxVacmViewTreeFamilyRowStatus = 3;

  public static final OID vacmViewTreeFamilyEntryOID =
      new OID(new int[] {1,3,6,1,6,3,16,1,5,2,1});

  public static final int vacmViewIncluded = MutableVACM.VACM_VIEW_INCLUDED;
  public static final int vacmViewExcluded = MutableVACM.VACM_VIEW_EXCLUDED;

  private static final int[] vacmViewTreeFamilyTypeValues = {
      vacmViewIncluded, vacmViewExcluded
  };

  private static MOTableSubIndex[] vacmViewTreeFamilyIndexes =
      new MOTableSubIndex[] {
      new MOTableSubIndex(SMIConstants.SYNTAX_OCTET_STRING, 1, 32),
      new MOTableSubIndex(SMIConstants.SYNTAX_OBJECT_IDENTIFIER, 0, 96)
  };

  private static MOTableIndex vacmViewTreeFamilyIndex =
      new MOTableIndex(vacmViewTreeFamilyIndexes);

  private static MOTableSubIndex[] vacmAccessIndexes = new MOTableSubIndex[] {
      new MOTableSubIndex(SMIConstants.SYNTAX_OCTET_STRING, 1, 32),
      new MOTableSubIndex(SMIConstants.SYNTAX_OCTET_STRING, 0, 32),
      new MOTableSubIndex(SMIConstants.SYNTAX_INTEGER, 1, 1),
      new MOTableSubIndex(SMIConstants.SYNTAX_INTEGER, 1, 1)
  };

  private static MOTableIndex vacmAccessIndex =
      new MOTableIndex(vacmAccessIndexes) {
    public boolean isValidIndex(OID index) {
      boolean ok = super.isValidIndex(index);
      if (ok) {
        SecurityModels secModels = SecurityModels.getInstance();
        Integer32 secModel = new Integer32(index.get(index.size()-2));
        if ((secModel.getValue() != SecurityModel.SECURITY_MODEL_ANY) &&
            (secModels.getSecurityModel(secModel) == null)) {
          return false;
        }
        int secLevel = index.get(index.size()-1);
        if ((secLevel < 1) || (secLevel > 3)) {
          return false;
        }
      }
      return ok;
    }
  };

  private MOServer[] server;

  private DefaultMOTable vacmContextTable;

  private DefaultMOTable vacmSecurityToGroupTable;
  private DefaultMOMutableTableModel vacmSecurityToGroupTableModel;

  private DefaultMOTable vacmAccessTable;
  private DefaultMOMutableTableModel vacmAccessTableModel;

  private TestAndIncr vacmViewSpinLock;

  private DefaultMOTable vacmViewTreeFamilyTable;
  private DefaultMOMutableTableModel vacmViewTreeFamilyTableModel;


  public VacmMIB(MOServer[] server) {
    this.server = server;
    createVacmContextTable();
    createVacmSecuritToGroupTable();
    createVacmAccessTable();
    createVacmViewTreeFamilyTable();
    vacmViewSpinLock = new TestAndIncr(vacmViewSpinLockOID);
  }

  public void registerMOs(MOServer server, OctetString context) throws
      DuplicateRegistrationException {
    server.register(vacmContextTable, context);
    server.register(vacmSecurityToGroupTable, context);
    server.register(vacmAccessTable, context);
    server.register(vacmViewSpinLock, context);
    server.register(vacmViewTreeFamilyTable, context);
  }

  private void createVacmContextTable() {
    MOTableSubIndex[] vacmContextTableIndexes = new MOTableSubIndex[] {
        new MOTableSubIndex(SMIConstants.SYNTAX_OCTET_STRING, 0, 32) };
    MOTableIndex vacmContextTableIndex =
        new MOTableIndex(vacmContextTableIndexes);
    MOColumn[] vacmContextColumns = new MOColumn[] {
        new MOColumn(1, SMIConstants.SYNTAX_OCTET_STRING,
                     MOAccessImpl.ACCESS_READ_ONLY) };

    this.vacmContextTable =
        new DefaultMOTable(vacmContextEntryOID, vacmContextTableIndex,
                           vacmContextColumns);
    this.vacmContextTable.setVolatile(true);
    this.vacmContextTable.setModel(new VacmContextTableModel());
  }

  private void createVacmSecuritToGroupTable() {
    MOTableSubIndex[] vacmSecurityToGroupIndexes = new MOTableSubIndex[] {
        new MOTableSubIndex(SMIConstants.SYNTAX_INTEGER, 1, 1),
        new MOTableSubIndex(SMIConstants.SYNTAX_OCTET_STRING, 1, 32) };

    MOTableIndex vacmSecurityToGroupIndex =
        new MOTableIndex(vacmSecurityToGroupIndexes) {
      public boolean isValidIndex(OID index) {
        boolean ok = super.isValidIndex(index);
        if (ok) {
          SecurityModels secModels = SecurityModels.getInstance();
          if (secModels.getSecurityModel(new Integer32(index.get(0))) == null) {
            return false;
          }
        }
        return ok;
      }
    };

    MOColumn[] vacmSecurityToGroupColumns = new MOColumn[] {
        new SnmpAdminString(colVacmGroupName,
                            MOAccessImpl.ACCESS_READ_CREATE, null, true, 1, 32),
        new StorageType(colVacmSecurityToGroupStorageType,
                        MOAccessImpl.ACCESS_READ_CREATE,
                        new Integer32(StorageType.nonVolatile), true),
        new RowStatus(colVacmSecurityToGroupRowStatus)
    };

    this.vacmSecurityToGroupTable =
        new DefaultMOTable(vacmSecurityToGroupEntryOID,
                           vacmSecurityToGroupIndex,
                           vacmSecurityToGroupColumns);
    vacmSecurityToGroupTableModel = new DefaultMOMutableTableModel();
    vacmSecurityToGroupTableModel.setRowFactory(new DefaultMOMutableRow2PCFactory());
    this.vacmSecurityToGroupTable.setModel(vacmSecurityToGroupTableModel);
  }

  private void createVacmAccessTable() {
    MOColumn[] vacmAccessColumns = new MOColumn[] {
        new Enumerated(colVacmAccessContextMatch,
                        MOAccessImpl.ACCESS_READ_CREATE,
                        new Integer32(vacmExactMatch), true,
                        new int[] { vacmExactMatch, vacmPrefixMatch }),
        new SnmpAdminString(colVacmAccessReadViewName,
                            MOAccessImpl.ACCESS_READ_CREATE,
                            new OctetString(), true, 0, 32),
        new SnmpAdminString(colVacmAccessWriteViewName,
                            MOAccessImpl.ACCESS_READ_CREATE,
                            new OctetString(), true, 0, 32),
        new SnmpAdminString(colVacmAccessNotifyViewName,
                            MOAccessImpl.ACCESS_READ_CREATE,
                            new OctetString(), true, 0, 32),
        new StorageType(colVacmAccessStorageType,
                        MOAccessImpl.ACCESS_READ_CREATE,
                        new Integer32(StorageType.nonVolatile), true),
        new RowStatus(colVacmAccessRowStatus)
    };

    vacmAccessTable = new DefaultMOTable(vacmAccessEntryOID,
                                         vacmAccessIndex,
                                         vacmAccessColumns);
    vacmAccessTableModel = new DefaultMOMutableTableModel();
    vacmAccessTableModel.setRowFactory(new DefaultMOMutableRow2PCFactory());
    vacmAccessTable.setModel(vacmAccessTableModel);
  }

  private void createVacmViewTreeFamilyTable() {
    MOColumn[] vacmViewTreeFamilyColumns = new MOColumn[] {
        new SnmpAdminString(colVacmViewTreeFamilyMask,
                            MOAccessImpl.ACCESS_READ_CREATE,
                            new OctetString(), true, 0, 16),
        new Enumerated(colVacmViewTreeFamilyType,
                        MOAccessImpl.ACCESS_READ_CREATE,
                        new Integer32(vacmViewIncluded), true,
                        vacmViewTreeFamilyTypeValues),
        new StorageType(colVacmViewTreeFamilyStorageType,
                        MOAccessImpl.ACCESS_READ_CREATE,
                        new Integer32(StorageType.nonVolatile), true),
        new RowStatus(colVacmViewTreeFamilyRowStatus)
    };

    vacmViewTreeFamilyTable = new DefaultMOTable(vacmViewTreeFamilyEntryOID,
                                                 vacmViewTreeFamilyIndex,
                                                 vacmViewTreeFamilyColumns);
    vacmViewTreeFamilyTableModel = new DefaultMOMutableTableModel();
    vacmViewTreeFamilyTableModel.setRowFactory(new DefaultMOMutableRow2PCFactory());
    vacmViewTreeFamilyTable.setModel(vacmViewTreeFamilyTableModel);
  }

  public void unregisterMOs(MOServer server, OctetString context) {
    server.unregister(this.vacmContextTable, context);
    server.unregister(this.vacmSecurityToGroupTable, context);
    server.unregister(this.vacmAccessTable, context);
    server.unregister(vacmViewSpinLock, context);
    server.unregister(vacmViewTreeFamilyTable, context);
  }

  public int isAccessAllowed(OctetString context, OctetString securityName,
                             int securityModel, int securityLevel, int viewType,
                             OID oid) {
    if (logger.isDebugEnabled()) {
      logger.debug("VACM access requested for context="+context+
                   ", securityName="+securityName+
                   ", securityModel="+securityModel+
                   ", securityLevel="+securityLevel+
                   ", viewType="+viewType+
                   ", OID="+oid);
    }
    boolean supported = isContextSupported(context);
    if (!supported) {
      if (logger.isDebugEnabled()) {
        logger.debug("Context '"+context+"' ist not supported");
      }
      return VACM.VACM_NO_SUCH_CONTEXT;
    }
    OctetString groupName = getGroupName(securityName, securityModel);
    if (groupName == null) {
      if (logger.isDebugEnabled()) {
        logger.debug("No group name for securityName="+securityName+
                     " and securityModel="+securityModel);
      }
      return VACM.VACM_NO_GROUP_NAME;
    }
    OctetString viewName = getViewNameByGroup(context, securityModel,
                                              securityLevel, viewType,
                                              groupName);
    if (viewName == null) {
      return VACM.VACM_NO_ACCESS_ENTRY;
    }
    if (viewName.length() == 0) {
      return VACM.VACM_NO_SUCH_VIEW;
    }
    return isAccessAllowed(viewName, oid);
  }

  private boolean isContextSupported(OctetString context) {
    boolean supported = false;
    for (int i=0; i= 0; v--) {
      MOTableRow row = (MOTableRow) views.get(v);
      if (((Integer32)row.getValue(idxVacmViewTreeFamilyRowStatus)).getValue()!=
          RowStatus.active) {
        // only active rows are relevant
        continue;
      }
      OID index = row.getIndex();
      Variable[] indexValues = vacmViewTreeFamilyIndex.getIndexValues(index);
      OID subtree = (OID) indexValues[idxVacmViewTreeSubtree];
      if (oid.size() < subtree.size()) {
        // no match
        continue;
      }
      OctetString mask = (OctetString) row.getValue(idxVacmViewTreeFamilyMask);
      boolean match = true;
      for (int i=0; itrue when the entry has been removed or false
   *    if such a mapping could not be found.
   */
  public boolean removeGroup(int securityModel, OctetString securityName) {
    OID index = createGroupIndex(securityModel, securityName);
    return (vacmSecurityToGroupTable.removeRow(index) != null);
  }

  /**
   * Adds an access entry to this VACM and thus adds access rights for a group.
   * @param groupName
   *    the group for which access rights are to be added.
   * @param contextPrefix
   *    the context or context prefix.
   * @param securityModel
   *    the security model
   * @param securityLevel
   *    the security level
   * @param match
   *    indicates whether exact context match ({@link #vacmExactMatch})
   *    or prefix context match ({@link #vacmPrefixMatch}) should
   *    be used by the new entry.
   * @param readView
   *    the view name for read access (use a zero length OctetString to disable
   *    access).
   * @param writeView
   *    the view name for write access (use a zero length OctetString to disable
   *    access).
   * @param notifyView
   *    the view name for notify access (use a zero length OctetString to
   *    disable access).
   * @param storageType
   *    the {@link StorageType} for this access entry.
   */
  public void addAccess(OctetString groupName, OctetString contextPrefix,
                        int securityModel, int securityLevel,
                        int match,
                        OctetString readView, OctetString writeView,
                        OctetString notifyView, int storageType) {
    OID index = createAccessIndex(groupName, contextPrefix, securityModel,
                                  securityLevel);
    Variable[] values = new Variable[vacmAccessTable.getColumnCount()];
    values[idxVacmAccessContextMatch] = new Integer32(match);
    values[idxVacmAccessReadViewName] = readView;
    values[idxVacmAccessWriteViewName] = writeView;
    values[idxVacmAccessNotifyViewName] = notifyView;
    values[idxVacmAccessStorageType] = new Integer32(storageType);
    values[idxVacmAccessRowStatus] = new Integer32(RowStatus.active);
    vacmAccessTable.addRow(vacmAccessTableModel.createRow(index, values));
  }

  /**
   * Removes an access entry from this VACM.
   * @param groupName
   *    the group for which access rights are to be added.
   * @param contextPrefix
   *    the context or context prefix.
   * @param securityModel
   *    the security model
   * @param securityLevel
   *    the security level
   * @return
   *    true when the entry has been removed or false
   *    if no such entry could be found.
   */
  public boolean removeAccess(OctetString groupName, OctetString contextPrefix,
                              int securityModel, int securityLevel) {
    OID index = createAccessIndex(groupName, contextPrefix, securityModel,
                                  securityLevel);
    return (vacmAccessTable.removeRow(index) != null);
  }

  private static OID createAccessIndex(OctetString groupName,
                                       OctetString contextPrefix,
                                       int securityModel, int securityLevel) {
    OID index = groupName.toSubIndex(false);
    index.append(contextPrefix.toSubIndex(false));
    index.append(securityModel);
    index.append(securityLevel);
    return index;
  }

  /**
   * Adds a new view to this VACM. An already existing entry with the same
   * view name and subtree OID will be replaced silently.
   * @param viewName
   *    the view name.
   * @param subtree
   *    the subtree OID.
   * @param mask
   *    the bit mask which, in combination with subtree,
   *    defines a family of view subtrees.
   * @param type
   *    indicates whether the view defined by subtree and
   *    mask is included ({@link #vacmViewIncluded}) or excluded
   *    (@link #vacmViewExcluded}) from the MIB view.
   * @param storageType
   *    the {@link StorageType} for this access entry.
   */
  public void addViewTreeFamily(OctetString viewName, OID subtree,
                                OctetString mask, int type, int storageType) {
    OID index = createViewIndex(viewName, subtree);
    Variable[] values = new Variable[vacmViewTreeFamilyTable.getColumnCount()];
    values[idxVacmViewTreeFamilyMask] = mask;
    values[idxVacmViewTreeFamilyType] = new Integer32(type);
    values[idxVacmViewTreeFamilyStorageType] = new Integer32(storageType);
    values[idxVacmViewTreeFamilyRowStatus] = new Integer32(RowStatus.active);
    MOTableRow row = vacmViewTreeFamilyTableModel.createRow(index, values);
    vacmViewTreeFamilyTable.addRow(row);
  }

  /**
   * Removes a view tree family from this VACM.
   * @param viewName
   *    the view name.
   * @param subtree
   *    the subtree OID.
   * @return
   *    true when the entry has been removed or false
   *    if no such entry could be found.
   */
  public boolean removeViewTreeFamily(OctetString viewName, OID subtree) {
    OID index = createViewIndex(viewName, subtree);
    return (vacmViewTreeFamilyTable.removeRow(index) != null);
  }

  private static OID createViewIndex(OctetString viewName, OID subtree) {
    OID index = viewName.toSubIndex(false);
    index.append(subtree.toSubIndex(false));
    return index;
  }

  /**
   * Checks whether bit n of the supplied OctetString is set or not.
   * @param n
   *    denotes the bit to check starting from zero.
   * @param os OctetString
   * @return boolean
   */
  private static boolean isBitSet(final int n, final OctetString os) {
    if (os.length() <= n/8) {
      return true;
    }
    return (os.get(n/8) & (0x01 << (7 - (n % 8)))) > 0;
  }

  private List getAccessEntries(OctetString groupName) {
    OctetString upperBound = new OctetString(groupName);
    byte last = -1;
    if (upperBound.length() > 0) {
      last = upperBound.get(upperBound.length() - 1);
    }
    if (last == -1) {
      upperBound.append((byte)0);
    }
    else {
      upperBound.set(upperBound.length()-1, (byte)(last+1));
    }
    OID lowerOID = groupName.toSubIndex(false);
    OID upperOID = upperBound.toSubIndex(false);
    List views = vacmAccessTableModel.getRows(lowerOID, upperOID);
    return views;
  }

  private List getViews(OctetString viewName) {
    if (viewName.length() == 0) {
      return Collections.EMPTY_LIST;
    }
    OctetString upperBound = new OctetString(viewName);
    byte last = upperBound.get(upperBound.length()-1);
    if (last == -1) {
      upperBound.append((byte)0);
    }
    else {
      upperBound.set(upperBound.length()-1, (byte)(last+1));
    }
    OID lowerOID = viewName.toSubIndex(false);
    OID upperOID = upperBound.toSubIndex(false);
    List views = vacmViewTreeFamilyTableModel.getRows(lowerOID, upperOID);
    return views;
  }

  public static class VacmContextIterator implements Iterator {

    private int index = 0;
    private OctetString[] contexts;

    VacmContextIterator(OctetString[] contexts, int offset) {
      this.contexts = contexts;
      this.index = offset;
    }

    public void remove() {
      throw new UnsupportedOperationException();
    }

    public boolean hasNext() {
      return (index < contexts.length);
    }

    public Object next() {
      if (index < contexts.length) {
        OctetString context = contexts[index++];
        DefaultMOTableRow row =
            new DefaultMOTableRow(context.toSubIndex(false),
                                  new Variable[] { context });
        return row;
      }
      throw new NoSuchElementException();
    }

  }

  private static OctetString getContextFromIndex(OID index) {
    if (index.size() > 0) {
      return new OctetString(index.toByteArray(), 1, index.size() - 1);
    }
    return new OctetString();
  }


  class VacmContextTableModel implements MOTableModel {

    public int getColumnCount() {
      return 1;
    }

    public int getRowCount() {
      int n = 0;
      for (int i=0; i




© 2015 - 2024 Weber Informatics LLC | Privacy Policy