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

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

There is a newer version: 3.8.1
Show newest version
/*_############################################################################
  _## 
  _##  SNMP4J-Agent 3 - UsmMIB.java  
  _## 
  _##  Copyright (C) 2005-2018  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 org.snmp4j.agent.*;
import org.snmp4j.agent.mo.*;
import org.snmp4j.security.dh.DHOperations;
import org.snmp4j.agent.mo.snmp.dh.SnmpUsmDhObjectsMib;
import org.snmp4j.agent.request.*;
import org.snmp4j.event.*;
import org.snmp4j.mp.*;
import org.snmp4j.security.*;
import org.snmp4j.smi.*;
import org.snmp4j.PDU;
import org.snmp4j.agent.mo.DefaultMOTable.ChangeSet;
import org.snmp4j.log.LogAdapter;
import org.snmp4j.log.LogFactory;

import java.util.Arrays;
import java.util.List;

/**
 * The {@code UsmMIB} implements the SNMP-USER-BASED-SM-MIB defined in
 * RFC 3414. The MIB implementation is backed by a {@link USM} instance.
 * The configuration of the user based security model can be changed
 * using the underlying {@link USM} or via SNMP but at
 * least one user must be created programatically in order to allow any access
 * to the agent via SNMP.
 * 

* When modifying the USM after having created this MIB, you will have to * register this object as {@link UsmUserListener} to the USM. *

* By using SNMP, a new users can only be created by cloning it from an existing * user with the same or higher security level. * * @author Frank Fock * @version 1.2 */ public class UsmMIB implements MOGroup, CounterListener, MOValueValidationListener, MOTableRowListener, UsmUserListener { private static final LogAdapter logger = LogFactory.getLogger(UsmMIB.class); public static final OID noAuthProtocol = new OID(new int[]{1, 3, 6, 1, 6, 3, 10, 1, 1, 1}); public static final OID noPrivProtocol = new OID(new int[]{1, 3, 6, 1, 6, 3, 10, 1, 2, 1}); public static final OID usmUserSpinLockOID = new OID(new int[]{1, 3, 6, 1, 6, 3, 15, 1, 2, 1, 0}); public static final OID usmUserEntryOID = new OID(new int[]{1, 3, 6, 1, 6, 3, 15, 1, 2, 2, 1}); public static final int colUsmUserSecurityName = 0; public static final int colUsmUserCloneFrom = 1; public static final int colUsmUserAuthProtocol = 2; public static final int colUsmUserAuthKeyChange = 3; public static final int colUsmUserOwnAuthKeyChange = 4; public static final int colUsmUserPrivProtocol = 5; public static final int colUsmUserPrivKeyChange = 6; public static final int colUsmUserOwnPrivKeyChange = 7; public static final int colUsmUserPublic = 8; public static final int colUsmUserStorageType = 9; public static final int colUsmUserStatus = 10; // hidden virtual columns public static final int colUsmUserAuthPassword = 11; public static final int colUsmUserPrivPassword = 12; public static final int colUsmUserLocalizationEngineID = 13; public static final int colUsmUserAuthKey = 14; public static final int colUsmUserPrivKey = 15; private static final int[][] keyChangeColumns = {{colUsmUserAuthKeyChange, colUsmUserOwnAuthKeyChange}, {colUsmUserPrivKeyChange, colUsmUserOwnPrivKeyChange} }; private USM usm; private SecurityProtocols securityProtocols; private static final OID usmStatsPrefix = new OID(SnmpConstants.usmStatsUnsupportedSecLevels.getValue(), 0, SnmpConstants.usmStatsUnsupportedSecLevels.size() - 2); private static final OID[] usmStatOIDs = new OID[]{ SnmpConstants.usmStatsUnsupportedSecLevels, SnmpConstants.usmStatsNotInTimeWindows, SnmpConstants.usmStatsUnknownUserNames, SnmpConstants.usmStatsUnknownEngineIDs, SnmpConstants.usmStatsWrongDigests, SnmpConstants.usmStatsDecryptionErrors }; private MOScalar[] usmStats; private TestAndIncr usmUserSpinLock; @SuppressWarnings("rawtypes") private DefaultMOTable> usmUserEntry; private UsmTableModel usmUserTableModel; private volatile boolean usmEventProcessing; /** * Creates a USM MIB implementation connected to the supplied USM. The MIB * contents will reflect any changes to the USM after completion of this * constructor if you register this object as {@link UsmUserListener} to the * USM! * * @param usm * a User-based Security Model. * @param securityProtocols * the supported {@code SecurityProtocols}. */ public UsmMIB(USM usm, SecurityProtocols securityProtocols) { this.usm = usm; this.securityProtocols = securityProtocols; usm.getCounterSupport().addCounterListener(this); createUsmStats(); createUsmUser(); } private void createUsmUser() { usmUserSpinLock = new TestAndIncr(usmUserSpinLockOID); MOTableSubIndex[] usmUserSubIndexes = new MOTableSubIndex[]{ new MOTableSubIndex(SMIConstants.SYNTAX_OCTET_STRING, 5, 32), new MOTableSubIndex(SMIConstants.SYNTAX_OCTET_STRING, 1, 32) }; MOColumn[] usmUserColumns = new MOColumn[]{ new SnmpAdminString(colUsmUserSecurityName + 3, MOAccessImpl.ACCESS_READ_ONLY, null, false), new UsmRowPointer(colUsmUserCloneFrom + 3, MOAccessImpl.ACCESS_READ_CREATE, null, true), new AutonomousType(colUsmUserAuthProtocol + 3, MOAccessImpl.ACCESS_READ_CREATE, noAuthProtocol, true), new UsmKeyChange(colUsmUserAuthKeyChange + 3, MOAccessImpl.ACCESS_READ_CREATE, UsmKeyChange.AUTH_KEY_CHANGE), new UsmOwnKeyChange(colUsmUserOwnAuthKeyChange + 3, MOAccessImpl.ACCESS_READ_CREATE, UsmKeyChange.AUTH_KEY_CHANGE), new AutonomousType(colUsmUserPrivProtocol + 3, MOAccessImpl.ACCESS_READ_CREATE, noPrivProtocol, true), new UsmKeyChange(colUsmUserPrivKeyChange + 3, MOAccessImpl.ACCESS_READ_CREATE, UsmKeyChange.PRIV_KEY_CHANGE), new UsmOwnKeyChange(colUsmUserOwnPrivKeyChange + 3, MOAccessImpl.ACCESS_READ_CREATE, UsmKeyChange.PRIV_KEY_CHANGE), new SnmpAdminString(colUsmUserPublic + 3, MOAccessImpl.ACCESS_READ_CREATE, new OctetString(), true, 0, 32), new StorageType(colUsmUserStorageType + 3, MOAccessImpl.ACCESS_READ_CREATE, new Integer32(StorageType.nonVolatile), true), new RowStatus(colUsmUserStatus + 3, MOAccessImpl.ACCESS_READ_CREATE) }; MOTableIndex usmUserIndex = new MOTableIndex(usmUserSubIndexes, false); usmUserTableModel = new UsmTableModel(usmUserIndex); usmUserEntry = new DefaultMOTable<>(usmUserEntryOID, usmUserIndex, usmUserColumns, usmUserTableModel) { @Override protected void fireRowChanged(MOTableRowEvent event) { if (super.moTableRowListeners != null) { List> listeners = super.moTableRowListeners; for (MOTableRowListener l : listeners) { if ((!usmEventProcessing) || (!(l instanceof UsmMIB))) { l.rowChanged(event); } } } } }; ((AutonomousType) usmUserColumns[colUsmUserAuthProtocol]).addMOValueValidationListener(this); ((AutonomousType) usmUserColumns[colUsmUserPrivProtocol]).addMOValueValidationListener(this); ((UsmRowPointer) usmUserColumns[colUsmUserCloneFrom]).setTargetTable(usmUserEntry); usmUserEntry.addMOTableRowListener(this); } public OID getProtocolForKeyChange(Request request, OID rowIndex, DHOperations.KeyType keyType) { ChangeSet changeSet = getUsmUserEntry().getRowPreview(request, rowIndex); OID cloneFrom = (OID) changeSet.getValue(colUsmUserCloneFrom); if ((cloneFrom != null) && (cloneFrom.size() > usmUserEntryOID.size())) { OID cloneRowIndex = new OID(cloneFrom.getValue(), usmUserEntryOID.size() + 1, cloneFrom.size() - (usmUserEntryOID.size() + 1)); ChangeSet changeSetClone = getUsmUserEntry().getRowPreview(request, cloneRowIndex); return getProtocolForKeyChangeWithoutCloneFrom(changeSetClone, keyType); } return getProtocolForKeyChangeWithoutCloneFrom(changeSet, keyType); } private OID getProtocolForKeyChangeWithoutCloneFrom(ChangeSet changeSet, DHOperations.KeyType keyType) { OID result = null; switch (keyType) { case authKeyChange: result = (OID) changeSet.getValue(colUsmUserAuthProtocol); break; case privKeyChange: result = (OID) changeSet.getValue(colUsmUserPrivProtocol); break; } if (noAuthProtocol.equals(result) || noPrivProtocol.equals(result)) { return null; } return result; } private void createUsmStats() { usmStats = new MOScalar[usmStatOIDs.length]; for (int i = 0; i < usmStats.length; i++) { usmStats[i] = new MOScalar<>(usmStatOIDs[i], MOAccessImpl.ACCESS_READ_ONLY, new Counter32(0)); } } public SecurityProtocols getSecurityProtocols() { return securityProtocols; } public void registerMOs(MOServer server, OctetString context) throws DuplicateRegistrationException { for (MOScalar usmStat : usmStats) { server.register(usmStat, context); } server.register(usmUserSpinLock, context); server.register(usmUserEntry, context); } public void unregisterMOs(MOServer server, OctetString context) { for (MOScalar usmStat : usmStats) { server.unregister(usmStat, context); } server.unregister(usmUserSpinLock, context); server.unregister(usmUserEntry, context); } public void incrementCounter(CounterEvent event) { if ((event.getOid().startsWith(usmStatsPrefix)) && (event.getOid().size() > usmStatsPrefix.size())) { Counter32 current = (Counter32)usmStats[event.getOid().get(usmStatsPrefix.size()) - 1].getValue(); current.increment(); event.setCurrentValue((Counter32) current.clone()); } } public void validate(MOValueValidationEvent validationEvent) { if (validationEvent.getSource() instanceof MOColumn) { MOColumn col = (MOColumn) validationEvent.getSource(); switch (col.getColumnID() - 4) { case colUsmUserAuthProtocol: { OID value = (OID) validationEvent.getNewValue(); if (!noAuthProtocol.equals(value)) { AuthenticationProtocol authProtocol = securityProtocols.getAuthenticationProtocol((OID) validationEvent.getNewValue()); if (authProtocol == null) { validationEvent.setValidationStatus(SnmpConstants.SNMP_ERROR_WRONG_VALUE); } } break; } case colUsmUserPrivProtocol: { OID value = (OID) validationEvent.getNewValue(); if (!noPrivProtocol.equals(value)) { PrivacyProtocol privProtocol = SecurityProtocols.getInstance().getPrivacyProtocol(value); if (privProtocol == null) { validationEvent.setValidationStatus(SnmpConstants.SNMP_ERROR_WRONG_VALUE); } } break; } } } } private Variable[] getValuesFromUsmUser(UsmUserEntry user) { Variable[] row = new Variable[usmUserEntry.getColumnCount() + 5]; int n = 0; row[n++] = user.getUsmUser().getSecurityName(); row[n++] = null; row[n++] = user.getUsmUser().getAuthenticationProtocol(); row[n++] = null; row[n++] = null; row[n++] = user.getUsmUser().getPrivacyProtocol(); row[n++] = null; row[n++] = null; row[n++] = new OctetString(); row[n++] = new Integer32(user.getStorageType().getSmiValue()); row[n++] = new Integer32(RowStatus.active); row[n++] = user.getUsmUser().getAuthenticationPassphrase(); row[n++] = user.getUsmUser().getPrivacyPassphrase(); row[n++] = user.getUsmUser().getLocalizationEngineID(); row[n++] = (user.getAuthenticationKey() == null) ? null : new OctetString(user.getAuthenticationKey()); row[n] = (user.getPrivacyKey() == null) ? null : new OctetString(user.getPrivacyKey()); return row; } private OID createIndex(OctetString engineID, OctetString userName) { if (engineID == null || engineID.length() == 0) { engineID = usm.getLocalEngineID(); } OID index = engineID.toSubIndex(false); index.append(userName.toSubIndex(false)); return index; } public synchronized void usmUserChange(UsmUserEvent event) { usmEventProcessing = true; switch (event.getType()) { case UsmUserEvent.USER_ADDED: { Variable[] values = getValuesFromUsmUser(event.getUser()); OID index = createIndex(event.getUser().getEngineID(), event.getUser().getUserName()); UsmMIB.UsmTableRow row = usmUserEntry.createRow(index, values); usmUserEntry.addRow(row); break; } case UsmUserEvent.USER_REMOVED: { if (event.getUser() == null) { usmUserTableModel.clear(); } else { OID index = createIndex(event.getUser().getEngineID(), event.getUser().getUserName()); usmUserEntry.removeRow(index); } break; } case UsmUserEvent.USER_CHANGED: { OID index = createIndex(event.getUser().getEngineID(), event.getUser().getUserName()); UsmMIB.UsmTableRow row = usmUserEntry.getModel().getRow(index); if (row != null) { UsmUser user = event.getUser().getUsmUser(); row.setValue(colUsmUserAuthProtocol, user.getAuthenticationProtocol()); row.setValue(colUsmUserPrivProtocol, user.getPrivacyProtocol()); row.setValue(colUsmUserAuthPassword, user.getAuthenticationPassphrase()); row.setValue(colUsmUserPrivPassword, user.getPrivacyPassphrase()); row.setValue(colUsmUserLocalizationEngineID, user.getLocalizationEngineID()); row.setValue(colUsmUserAuthKey, (event.getUser().getAuthenticationKey() == null) ? null : new OctetString(event.getUser().getAuthenticationKey())); row.setValue(colUsmUserPrivKey, (event.getUser().getPrivacyKey() == null) ? null : new OctetString(event.getUser().getPrivacyKey())); } else { Variable[] values = getValuesFromUsmUser(event.getUser()); row = usmUserEntry.createRow(index, values); usmUserEntry.addRow(row); } break; } } usmEventProcessing = false; } public class UsmTableModel extends DefaultMOMutableTableModel { private MOTableIndex indexDef; public UsmTableModel(MOTableIndex indexDef) { super(); this.indexDef = indexDef; } public UsmMIB.UsmTableRow createRow(OID index, Variable[] values) { if (values.length < colUsmUserPrivKey + 1) { Variable[] h = new Variable[colUsmUserPrivKey + 1]; System.arraycopy(values, 0, h, 0, values.length); values = h; } return new UsmTableRow(this, index, values); } public MOTableIndex getIndexDef() { return indexDef; } } private static boolean isKeyChanged(MOTableRow changeSet, int keyChangeColumn) { OctetString value = (OctetString) changeSet.getValue(keyChangeColumn); return (value != null) && (value.length() > 0); } private static boolean isKeyChanged(MOTableRow changeSet) { return ((isKeyChanged(changeSet, colUsmUserOwnAuthKeyChange)) || (isKeyChanged(changeSet, colUsmUserAuthKeyChange)) || (isKeyChanged(changeSet, colUsmUserOwnPrivKeyChange)) || (isKeyChanged(changeSet, colUsmUserPrivKeyChange))); } public class UsmTableRow extends DefaultMOMutableRow2PC { private UsmTableModel tableModel; private boolean cloned = false; public UsmTableRow(UsmTableModel model, OID index, Variable[] values) { super(index, values); this.tableModel = model; } public void setCloned(boolean cloned) { this.cloned = cloned; } public boolean isCloned() { return cloned; } public MOTableIndex getIndexDef() { return tableModel.getIndexDef(); } public AuthenticationProtocol getAuthProtocol(MOTableRow changeSet) { OID authOID = getAuthProtocolOID(changeSet); return securityProtocols.getAuthenticationProtocol(authOID); } public PrivacyProtocol getPrivProtocol(MOTableRow changeSet) { OID privOID = getPrivProtocolOID(changeSet); return securityProtocols.getPrivacyProtocol(privOID); } /** * Gets the OID of the privacy protocol defined by the given * change set. If the change set defines {@link #noPrivProtocol} * {@code null} is returned. * * @param preparedChanges * a TableRow instance with UsmTableRow values. * * @return a privacy protocol OID or {@code null} if no * privacy protocol is defined by {@code changeSet}. */ public OID getPrivProtocolOID(MOTableRow preparedChanges) { OID privID = null; if (preparedChanges.getValue(colUsmUserCloneFrom) == null) { privID = (OID) preparedChanges.getValue(colUsmUserPrivProtocol); } if (privID == null) { privID = (OID) getValue(colUsmUserPrivProtocol); } if (noPrivProtocol.equals(privID)) { privID = null; } return privID; } public void prepare(SubRequest subRequest, MOTableRow preparedChanges, int column) { switch (column) { case colUsmUserAuthProtocol: { OID authProtocol = (OID) subRequest.getVariableBinding().getVariable(); if (!authProtocol.equals(noAuthProtocol)) { subRequest.getStatus().setErrorStatus(PDU.inconsistentValue); } else { OID privProtocol = null; Variable privProtocolVariable = preparedChanges.getValue(colUsmUserPrivProtocol); if (privProtocolVariable instanceof OID) { privProtocol = (OID) privProtocolVariable; } else if (privProtocolVariable == null) { privProtocol = (OID) getValue(colUsmUserPrivProtocol); } if ((privProtocol == null) || (!privProtocol.equals(noPrivProtocol))) { subRequest.getStatus().setErrorStatus(PDU.inconsistentValue); } } break; } case colUsmUserPrivProtocol: { OID privProtocol = (OID) subRequest.getVariableBinding().getVariable(); if (!privProtocol.equals(noPrivProtocol)) { subRequest.getStatus().setErrorStatus(PDU.inconsistentValue); } break; } } } private OID getCloneFromIndex(MOTableRow changeSet) { OID cloneFrom = (OID) changeSet.getValue(colUsmUserCloneFrom); if (cloneFrom == null) { cloneFrom = (OID) getValue(colUsmUserCloneFrom); } if ((cloneFrom == null) || (cloneFrom.size() <= usmUserEntryOID.size())) { return null; } return new OID(cloneFrom.getValue(), usmUserEntryOID.size() + 1, cloneFrom.size() - (usmUserEntryOID.size() + 1)); } public synchronized void commitRow(SubRequest subRequest, MOTableRow changeSet) { if (subRequest.hasError()) { return; } Variable[] indexValues = getIndexDef().getIndexValues(getIndex()); OctetString engineID = (OctetString) indexValues[0]; OctetString userName = (OctetString) indexValues[1]; UsmUserEntry oldUserEntry; OID cloneFromUserIndex = getCloneFromIndex(changeSet); if (cloneFromUserIndex != null) { Variable[] cloneFromIndexValues = getIndexDef().getIndexValues(cloneFromUserIndex); OctetString cloneFromEngineID = (OctetString) cloneFromIndexValues[0]; OctetString cloneFromUserName = (OctetString) cloneFromIndexValues[1]; oldUserEntry = usm.getUser(cloneFromEngineID, cloneFromUserName); // assign protocols if (oldUserEntry != null) { setValue(colUsmUserAuthProtocol, oldUserEntry.getUsmUser().getAuthenticationProtocol()); setValue(colUsmUserPrivProtocol, oldUserEntry.getUsmUser().getPrivacyProtocol()); } } else { oldUserEntry = usm.getUser(engineID, userName); } SnmpUsmDhObjectsMib.UsmDHUserKeyEntryRow dhUsmUserEntry = (SnmpUsmDhObjectsMib.UsmDHUserKeyEntryRow) usmUserEntry.getDependentTableRow(SnmpUsmDhObjectsMib.oidUsmDHUserKeyEntry, getIndex()); Integer32 newStatus = (Integer32) changeSet.getValue(colUsmUserStatus); if (((newStatus != null) && ((newStatus.getValue() == RowStatus.active) || (newStatus.getValue() == RowStatus.createAndGo))) || ((getValue(colUsmUserStatus) != null) && (((Integer32) getValue(colUsmUserStatus)).getValue() == RowStatus.active) && (isKeyChanged(changeSet) || (dhUsmUserEntry != null && dhUsmUserEntry.isKeyChangePending())))) { if (cloneFromUserIndex != null) { // save undo value setUserObject(oldUserEntry); } if (oldUserEntry == null) { subRequest.getStatus().setErrorStatus(PDU.commitFailed); return; } OctetString[] newKeys = new OctetString[2]; OctetString[] oldKeys = new OctetString[2]; AuthenticationProtocol a = getAuthProtocol(changeSet); if (a != null) { for (int p = 0; p < 2; p++) { byte[] k = ((p == 0) ? oldUserEntry.getAuthenticationKey() : oldUserEntry.getPrivacyKey()); oldKeys[p] = null; if (k != null) { oldKeys[p] = new OctetString(k); for (int i = 0; i < keyChangeColumns[p].length; i++) { OctetString keyChange = (OctetString) getValue(keyChangeColumns[p][i]); if ((keyChange != null) && (keyChange.length() > 0)) { int keyLength = a.getDigestLength(); OctetString doKey = oldKeys[p]; if (p == 1) { // privacy protocol key change PrivacyProtocol privProtocol = getPrivProtocol(changeSet); keyLength = privProtocol.getMaxKeyLength(); } newKeys[p] = KeyChange.changeKey(a, doKey, keyChange, keyLength); break; // only one key change per protocol } } if ((newKeys[p] == null) && (dhUsmUserEntry != null)) { // check for Diffie Hellman USM key exchange byte[] newKeyValue = (p == 0) ? dhUsmUserEntry.getNewAuthKey() : dhUsmUserEntry.getNewPrivKey(); if (newKeyValue != null) { newKeys[p] = new OctetString(newKeyValue); } } } } } UsmUserEntry newEntry = new UsmUserEntry(engineID.getValue(), userName, getAuthProtocolOID(changeSet), (newKeys[0] == null) ? ((oldKeys[0] == null) ? null : oldKeys[0].getValue()) : newKeys[0].getValue(), getPrivProtocolOID(changeSet), (newKeys[1] == null) ? ((oldKeys[1] == null) ? null : oldKeys[1].getValue()) : newKeys[1].getValue()); if (logger.isDebugEnabled()) { logger.debug("Modifying user keys from old " + Arrays.asList(oldKeys) + " to new " + Arrays.asList(newKeys)); } newEntry.setStorageType(getStorageType(changeSet)); usm.updateUser(newEntry); setValue(colUsmUserCloneFrom, null); clearKeyChangeObjects(); if (dhUsmUserEntry != null) { dhUsmUserEntry.clearDHKeyChange(); } } if (newStatus != null) { switch (newStatus.getValue()) { case RowStatus.createAndWait: case RowStatus.createAndGo: { setValue(colUsmUserSecurityName, userName); break; } } } } /** * Gets the OID of the authentication protocol defined by the given * change set. If the change set defines {@link #noAuthProtocol} * {@code null} is returned. * * @param changeSet * a TableRow instance with UsmTableRow values. * * @return an authentication protocol OID or {@code null} if no * authentication protocol is defined by {@code changeSet}. */ public OID getAuthProtocolOID(MOTableRow changeSet) { OID authID = null; if (changeSet.getValue(colUsmUserCloneFrom) == null) { authID = (OID) changeSet.getValue(colUsmUserAuthProtocol); } if (authID == null) { authID = (OID) getValue(colUsmUserAuthProtocol); } if (noAuthProtocol.equals(authID)) { authID = null; } return authID; } public void cleanupRow(SubRequest subRequest, ChangeSet changeSet) { setUserObject(null); } public void undoRow(SubRequest subRequest, ChangeSet changeSet) { if (getUserObject() != null) { usm.updateUser((UsmUserEntry) getUserObject()); } } Variable getCachedValue(int column) { return super.getValue(column); } public Variable getValue(int column) { if (column > colUsmUserStatus) { UsmUserEntry userEntry = getUserEntry(); if (userEntry != null) { switch (column) { case colUsmUserAuthPassword: setValue(column, userEntry.getUsmUser().getAuthenticationPassphrase()); break; case colUsmUserPrivPassword: setValue(column, userEntry.getUsmUser().getPrivacyPassphrase()); break; case colUsmUserLocalizationEngineID: setValue(column, (userEntry.getUsmUser().isLocalized()) ? userEntry.getUsmUser().getLocalizationEngineID() : null); break; case colUsmUserAuthKey: { byte[] key = userEntry.getAuthenticationKey(); setValue(column, (key == null) ? null : new OctetString(key)); break; } case colUsmUserPrivKey: { byte[] key = userEntry.getPrivacyKey(); setValue(column, (key == null) ? null : new OctetString(key)); break; } } } } return super.getValue(column); } public boolean containsHiddenValues() { for (int i = colUsmUserStatus + 1; i < values.length; i++) { if (values[i] != null) { return true; } } return false; } private UsmUserEntry getUserEntry() { Variable[] indexValues = getIndexDef().getIndexValues(getIndex()); OctetString engineID = (OctetString) indexValues[0]; OctetString userName = (OctetString) indexValues[1]; return usm.getUser(engineID, userName); } private OctetString[] getIndexValues() { Variable[] indexValues = getIndexDef().getIndexValues(getIndex()); OctetString[] idxValues = new OctetString[2]; idxValues[0] = (OctetString) indexValues[0]; idxValues[1] = (OctetString) indexValues[1]; return idxValues; } public void clearKeyChangeObjects() { setValue(colUsmUserAuthKeyChange, null); setValue(colUsmUserOwnAuthKeyChange, null); setValue(colUsmUserPrivKeyChange, null); setValue(colUsmUserOwnPrivKeyChange, null); } } private SnmpConstants.StorageTypeEnum getStorageType(MOTableRow changeSet) { Variable storageTypeValue = changeSet.getValue(colUsmUserStorageType); if (storageTypeValue != null) { return StorageType.StorageTypeEnum.toSnmpConstantsStorageTypeEnum(storageTypeValue.toInt()); } return null; } @SuppressWarnings("rawtypes") public DefaultMOTable> getUsmUserEntry() { return usmUserEntry; } class UsmRowPointer extends RowPointer { public UsmRowPointer(int columnID, MOAccess access, OID defaultValue, boolean mutableInService) { super(columnID, access, defaultValue, mutableInService); } public void prepare(SubRequest subRequest, MOTableRow row, MOTableRow changeSet, int column) { super.prepare(subRequest, row, changeSet, column); if (!subRequest.hasError()) { OID rowPointer = (OID) subRequest.getVariableBinding().getVariable(); MOTableCellInfo cell = getTargetTable().getCellInfo(rowPointer); if (cell.getIndex().equals(row.getIndex())) { // cannot clone from self subRequest.getStatus().setErrorStatus(PDU.inconsistentValue); } } } public OID getValue(MOTableRow row, int column) { return SnmpConstants.zeroDotZero; } } @Override public synchronized void rowChanged(MOTableRowEvent event) { UsmTableRow row = event.getRow(); if (event.getType() == MOTableRowEvent.CREATE && event.getOriginType() == MOTableRowEvent.OriginType.internal) { // check if event needs to be processed if (!row.containsHiddenValues() && ((row.getAuthProtocolOID(row) != null) || (row.getPrivProtocolOID(row) != null))) { logger.warn("Cannot add user with index '" + event.getRow().getIndex() + "' to the USM from USM-MIB because key information is missing"); return; } // loaded row UsmUserEntry entry = row.getUserEntry(); if (entry != null) { // remove existing users for later replacement usm.removeAllUsers(entry.getUserName(), entry.getEngineID()); } addOrUpdateUsmUserFromRow(row, false); } else if ((event.getOriginType() == MOTableRowEvent.OriginType.internal) && (event.getType() == MOTableRowEvent.UPDATED)) { addOrUpdateUsmUserFromRow(row, true); } else if (event.getType() == MOTableRowEvent.DELETE) { UsmUserEntry entry = row.getUserEntry(); if (entry != null) { usm.removeAllUsers(entry.getUserName(), entry.getEngineID()); } } } public static UsmUserEntry localizeUser(OctetString securityName, OctetString localizationEngineID, OID authProtocol, OctetString authPassphrase, OID privProtocol, OctetString privPassphrase, SecurityProtocols securityProtocols) { OctetString newAuthKey; OctetString newPrivKey; if (authProtocol != null && authPassphrase != null) { newAuthKey = new OctetString(securityProtocols.passwordToKey(authProtocol, authPassphrase, localizationEngineID.getValue())); } else { newAuthKey = null; } if (authProtocol != null && privProtocol != null && privPassphrase != null) { newPrivKey = new OctetString(securityProtocols.passwordToKey(privProtocol, authProtocol, privPassphrase, localizationEngineID.getValue())); } else { newPrivKey = null; } return new UsmUserEntry(localizationEngineID.getValue(), securityName, authProtocol, (newAuthKey == null) ? null : newAuthKey.getValue(), privProtocol, (newPrivKey == null) ? null : newPrivKey.getValue()); } private void addOrUpdateUsmUserFromRow(UsmTableRow row, boolean update) { OctetString[] idxValues = row.getIndexValues(); OctetString engineID = idxValues[0]; OctetString securityName = idxValues[1]; try { if ((row.size() > colUsmUserLocalizationEngineID) && (row.getCachedValue(colUsmUserAuthPassword) != null)) { UsmUserEntry usmUserEntry; if (update || row.getCachedValue(colUsmUserAuthKey) == null) { // localize passwords usmUserEntry = localizeUser(securityName, engineID, row.getAuthProtocolOID(row), (OctetString) row.getCachedValue(colUsmUserAuthPassword), row.getPrivProtocolOID(row), (OctetString) row.getCachedValue(colUsmUserPrivPassword), securityProtocols); row.setValue(colUsmUserAuthKey, (usmUserEntry.getAuthenticationKey() == null) ? null : new OctetString(usmUserEntry.getAuthenticationKey())); row.setValue(colUsmUserPrivKey, (usmUserEntry.getPrivacyKey() == null) ? null : new OctetString(usmUserEntry.getPrivacyKey())); } else { OctetString authKey = (OctetString) row.getCachedValue(colUsmUserAuthKey); OctetString privKey = (OctetString) row.getCachedValue(colUsmUserPrivKey); usmUserEntry = new UsmUserEntry(engineID.getValue(), securityName, row.getAuthProtocolOID(row), (authKey == null) ? null : authKey.getValue(), row.getPrivProtocolOID(row), (privKey == null) ? null : privKey.getValue()); } if (update) { usm.updateUser(usmUserEntry); } else { usm.addUsmUserEntry(usmUserEntry); } row.setValue(colUsmUserAuthPassword, null); row.setValue(colUsmUserPrivPassword, null); if (logger.isDebugEnabled()) { logger.debug((update ? "Updated" : "Added") + " user " + securityName + " and removed passwords from row"); } } else if (row.size() > colUsmUserPrivKey) { OctetString authKey = (OctetString) row.getCachedValue(colUsmUserAuthKey); OctetString privKey = (OctetString) row.getCachedValue(colUsmUserPrivKey); if (update) { usm.updateUser(new UsmUserEntry(engineID.getValue(), securityName, row.getAuthProtocolOID(row), (authKey == null) ? null : authKey.getValue(), row.getPrivProtocolOID(row), (privKey == null) ? null : privKey.getValue())); } else { usm.addLocalizedUser(engineID.getValue(), securityName, row.getAuthProtocolOID(row), (authKey == null) ? null : authKey.getValue(), row.getPrivProtocolOID(row), (privKey == null) ? null : privKey.getValue()); } } else { logger.warn("Cannot " + ((update) ? "update" : "add") + " user '" + idxValues[1] + "' to the USM from USM-MIB because key information is missing"); } } catch (NullPointerException npe) { logger.error("Cannot add/update user '"+idxValues[1]+ "' to USM because auth/priv protocol not available.", npe); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy