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

org.snmp4j.security.UsmUser Maven / Gradle / Ivy

There is a newer version: 3.8.2
Show newest version
/*_############################################################################
  _## 
  _##  SNMP4J - UsmUser.java  
  _## 
  _##  Copyright (C) 2003-2024  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.security;

import org.snmp4j.SNMP4JSettings;
import org.snmp4j.User;
import org.snmp4j.smi.OctetString;
import org.snmp4j.smi.OID;

import java.util.Objects;

/**
 * The {@code UsmUser} class represents USM user providing information
 * to secure SNMPv3 message exchange. A user is characterized by its security
 * name and optionally by a authentication protocol and passphrase as well as
 * a privacy protocol and passphrase.
 * 

* There are no setters for the attributes of this class, to prevent * inconsistent states in the USM, when a user is changed from outside. * Since version 3.8.0, the creator of instances of this class can define * for non-localized users for which kind of SNMP processing, i.e., incoming * or outgoing, localization is allowed. * * @author Frank Fock * @version 3.8.0 */ public class UsmUser implements User, Comparable, Cloneable { private static final long serialVersionUID = -2258973598142206767L; /** * This enum defines which Localization operations are allowed for a {@link UsmUser}. By default, and backward * compatibility, {@link LocalizationGrant#any} is the default. Use {@link #incoming} for users that * should receive notifications from unknown authoritative engine IDs. Use {@link #outgoing} if the user * must only be localized for command generators sending requests to command responders. * @since 3.8.0 */ public enum LocalizationGrant { /** * Never allow localization (does only make sense for non-localized users that should not be used * with USM request processing). This is the default for already localized users. */ never, /** * Allow localization for outgoing request processing where the using engine is non-authoritative, * i.e. a command generator is sending a request message. */ outgoing, /** * Allow localization for incoming message processing, i.e. receiving notifications. */ incoming, /** * Allow any localization (default). */ any }; private final OctetString securityName; private final SecretOctetString authenticationPassphrase; private final SecretOctetString privacyPassphrase; private final OID authenticationProtocol; private final OID privacyProtocol; private OctetString localizationEngineID; private LocalizationGrant localizationGrant = LocalizationGrant.any; /** * Creates a USM user. * @param securityName * the security name of the user (typically the username). * @param authenticationProtocol * the authentication protocol ID to be associated with this user. If set * to {@code null}, this user only supports unauthenticated messages. * @param authenticationPassphrase * the authentication passphrase. If not {@code null}, * {@code authenticationProtocol} must also be not {@code null}. * RFC3414 §11.2 requires passphrases to have a minimum length of 8 bytes. * If the length of {@code authenticationPassphrase} is less than 8 * bytes an {@code IllegalArgumentException} is thrown. * @param privacyProtocol * the privacy protocol ID to be associated with this user. If set * to {@code null}, this user only supports unencrypted messages. * @param privacyPassphrase * the privacy passphrase. If not {@code null}, * {@code privacyProtocol} must also be not {@code null}. * RFC3414 §11.2 requires passphrases to have a minimum length of 8 bytes. * If the length of {@code authenticationPassphrase} is less than 8 * bytes an {@code IllegalArgumentException} is thrown. */ public UsmUser(OctetString securityName, OID authenticationProtocol, OctetString authenticationPassphrase, OID privacyProtocol, OctetString privacyPassphrase) { this(securityName, authenticationProtocol, authenticationPassphrase, privacyProtocol, privacyPassphrase, LocalizationGrant.any); } /** * Creates a USM user. * @param securityName * the security name of the user (typically the username). * @param authenticationProtocol * the authentication protocol ID to be associated with this user. If set * to {@code null}, this user only supports unauthenticated messages. * @param authenticationPassphrase * the authentication passphrase. If not {@code null}, * {@code authenticationProtocol} must also be not {@code null}. * RFC3414 §11.2 requires passphrases to have a minimum length of 8 bytes. * If the length of {@code authenticationPassphrase} is less than 8 * bytes an {@code IllegalArgumentException} is thrown. * @param privacyProtocol * the privacy protocol ID to be associated with this user. If set * to {@code null}, this user only supports unencrypted messages. * @param privacyPassphrase * the privacy passphrase. If not {@code null}, * {@code privacyProtocol} must also be not {@code null}. * RFC3414 §11.2 requires passphrases to have a minimum length of 8 bytes. * If the length of {@code authenticationPassphrase} is less than 8 * bytes an {@code IllegalArgumentException} is thrown. * @param localizationGrant * defines for what kind of USM message processing this non-localized user is allowed to be localized. * Note: for automatic localization to happen, {@link USM#setEngineDiscoveryEnabled(boolean)} must be enabled. * @since 3.8.0 */ public UsmUser(OctetString securityName, OID authenticationProtocol, OctetString authenticationPassphrase, OID privacyProtocol, OctetString privacyPassphrase, LocalizationGrant localizationGrant) { if (securityName == null) { throw new NullPointerException(); } if (SNMP4JSettings.isCheckUsmUserPassphraseLength()) { if ((authenticationProtocol != null) && ((authenticationPassphrase != null) && (authenticationPassphrase.length() < USM.RFC3414_11_2_MIN_PASSWORD_LENGTH))) { throw new IllegalArgumentException( "USM passphrases must be at least 8 bytes long (RFC3414 §11.2)"); } if ((privacyProtocol != null) && ((privacyPassphrase != null) && (privacyPassphrase.length() < USM.RFC3414_11_2_MIN_PASSWORD_LENGTH))) { throw new IllegalArgumentException( "USM passphrases must be at least 8 bytes long (RFC3414 §11.2)"); } } this.securityName = securityName; this.authenticationProtocol = authenticationProtocol; this.authenticationPassphrase = SecretOctetString.fromOctetString(authenticationPassphrase); this.privacyProtocol = privacyProtocol; this.privacyPassphrase = SecretOctetString.fromOctetString(privacyPassphrase); this.localizationGrant = localizationGrant; } /** * Creates a localized USM user. * @param securityName * the security name of the user (typically the username). * @param authenticationProtocol * the authentication protcol ID to be associated with this user. If set * to {@code null}, this user only supports unauthenticated messages. * @param authenticationPassphrase * the authentication passphrase. If not {@code null}, * {@code authenticationProtocol} must also be not {@code null}. * RFC3414 §11.2 requires passphrases to have a minimum length of 8 bytes. * If the length of {@code authenticationPassphrase} is less than 8 * bytes an {@code IllegalArgumentException} is thrown. * @param privacyProtocol * the privacy protocol ID to be associated with this user. If set * to {@code null}, this user only supports unencrypted messages. * @param privacyPassphrase * the privacy passphrase. If not {@code null}, * {@code privacyProtocol} must also be not {@code null}. * RFC3414 §11.2 requires passphrases to have a minimum length of 8 bytes. * If the length of {@code authenticationPassphrase} is less than 8 * bytes an {@code IllegalArgumentException} is thrown. * @param localizationEngineID * if not {@code null}, the localizationEngineID specifies the * engine ID for which the supplied passphrases are already localized. * Such an USM user can only be used with the target whose engine ID * equals localizationEngineID. */ public UsmUser(OctetString securityName, OID authenticationProtocol, OctetString authenticationPassphrase, OID privacyProtocol, OctetString privacyPassphrase, OctetString localizationEngineID) { if (securityName == null) { throw new NullPointerException(); } this.securityName = securityName; this.authenticationProtocol = authenticationProtocol; this.authenticationPassphrase = SecretOctetString.fromOctetString(authenticationPassphrase); this.privacyProtocol = privacyProtocol; this.privacyPassphrase = SecretOctetString.fromOctetString(privacyPassphrase); this.localizationEngineID = localizationEngineID; this.localizationGrant = LocalizationGrant.never; } /** * Gets the user's security name. * @return * a clone of the user's security name. */ public OctetString getSecurityName() { return (OctetString) securityName.clone(); } /** * Gets the authentication protocol ID. * @return * a clone of the authentication protocol ID or {@code null}. */ public OID getAuthenticationProtocol() { if (authenticationProtocol == null) { return null; } return (OID) authenticationProtocol.clone(); } /** * Gets the privacy protocol ID. * @return * a clone of the privacy protocol ID or {@code null}. */ public OID getPrivacyProtocol() { if (privacyProtocol == null) { return null; } return (OID) privacyProtocol.clone(); } /** * Gets the authentication passphrase. * @return * a clone of the authentication passphrase or {@code null}. */ public OctetString getAuthenticationPassphrase() { if (authenticationPassphrase == null) { return null; } return (OctetString) authenticationPassphrase.clone(); } /** * Gets the privacy passphrase. * @return * a clone of the privacy passphrase or {@code null}. */ public OctetString getPrivacyPassphrase() { if (privacyPassphrase == null) { return null; } return (OctetString) privacyPassphrase.clone(); } /** * Returns the localization engine ID for which this USM user has been already * localized. * @return * {@code null} if this USM user is not localized or the SNMP engine * ID of the target for which this user has been localized. * @since 1.6 */ public OctetString getLocalizationEngineID() { return localizationEngineID; } /** * Indicates whether the passphrases of this USM user need to be localized * or not ({@code true} is returned in that case). * @return * {@code true} if the passphrases of this USM user represent * localized keys. * @since 1.6 */ public boolean isLocalized() { return (localizationEngineID != null); } /** * Check if the localization of this user is granted (and not yet done) for the requested localization kind. * @param requiredLocalizationGrant * the requested kind of localization. * @return * {«code true} if requested localization is granted and this user has not been localized yet. * For a required {@link LocalizationGrant#incoming}, {@link LocalizationGrant#incoming} or * {@link LocalizationGrant#any} is necessary, for example. * @since 3.8.0 */ public boolean isLocalizationGranted(LocalizationGrant requiredLocalizationGrant) { LocalizationGrant currentGrant = getLocalizationGrant(); if (currentGrant == LocalizationGrant.never || requiredLocalizationGrant == LocalizationGrant.never) { return false; } else if (currentGrant == LocalizationGrant.any) { return true; } else { return requiredLocalizationGrant == currentGrant; } } /** * Gets the security model ID of the USM. * @return * {@link USM#getID()} */ public int getSecurityModel() { return SecurityModel.SECURITY_MODEL_USM; } /** * Compares two USM users by their security names. * @param other * another {@code UsmUser} instance. * @return * a negative integer, zero, or a positive integer as this object is * less than, equal to, or greater than the specified object. */ public int compareTo(UsmUser other) { // allow only comparison with UsmUsers return securityName.compareTo(other.securityName); } public Object clone() { UsmUser copy = new UsmUser(this.securityName, this.authenticationProtocol, this.authenticationPassphrase, this.privacyProtocol, this.privacyPassphrase, this.localizationEngineID); copy.localizationGrant = this.localizationGrant; return copy; } /** * Return a copy of the current user with (updated) localized keys. * @param localizationEngineID * the {@code localizationEngineID} specifies the engine ID for which the supplied keys are already localized. * Such an USM user can only be used with the target whose engine ID equals {@code localizationEngineID}. * If {@code null}, then a {@link NullPointerException} will be thrown. * @param localizedAuthenticationKey * the optional new (localized) authentication key. If {@code null}, then the existing authentication key of this * user is preserved and it is returned by {@link UsmUser} in its localized representation. * @param localizedPrivacyKey * the optional new (localized) privacy key. If {@code null}, then the existing privacy key of this user * is preserved and it is returned by {@link UsmUser} in its localized representation. * @param securityProtocols * a collection of {@link SecurityProtocol} instances providing security protocols used by the * {@link SecurityProtocols#passwordToKey(OID, OctetString, byte[])} operation to localize existing passphrases. * If not provided (i.e. {@code null}) and at least one of the existing passphrases is not {@code null}, then * a {@link NullPointerException} is thrown. * @return * a copy of this user but with localized (optionally new) authentication or privacy keys. * @since 3.4.0 */ public UsmUser localizeUser(OctetString localizationEngineID, OctetString localizedAuthenticationKey, OctetString localizedPrivacyKey, SecurityProtocols securityProtocols) { if (getLocalizationEngineID() != null && !localizationEngineID.equals(getLocalizationEngineID()) && ((localizedAuthenticationKey == null) || localizedPrivacyKey == null)) { throw new IllegalArgumentException("Localization engine ID cannot be changed"); } if (localizationEngineID == null || localizationEngineID.length() == 0) { throw new NullPointerException(); } OctetString newAuthKey; OctetString newPrivKey; if (localizedAuthenticationKey == null) { if (getAuthenticationProtocol() != null && getAuthenticationPassphrase() != null) { newAuthKey = new SecretOctetString(securityProtocols.passwordToKey(getAuthenticationProtocol(), getAuthenticationPassphrase(), localizationEngineID.getValue())); } else { newAuthKey = null; } } else { newAuthKey = localizedAuthenticationKey; } if (localizedPrivacyKey == null) { if (getAuthenticationProtocol() != null && getPrivacyProtocol() != null && getPrivacyPassphrase() != null) { newPrivKey = new SecretOctetString(securityProtocols.passwordToKey(getPrivacyProtocol(), getAuthenticationProtocol(), getPrivacyPassphrase(), localizationEngineID.getValue())); } else { newPrivKey = null; } } else { newPrivKey = localizedPrivacyKey; } return new UsmUser(getSecurityName(), getAuthenticationProtocol(), newAuthKey, getPrivacyProtocol(), newPrivKey, localizationEngineID); } /** * Returns for which kind of {@link USM} request processing a localization of this user is allowed. * @return * the allowed localization options. For already localized users, {@link LocalizationGrant#never} is returned. * @since 3.8.0 */ public LocalizationGrant getLocalizationGrant() { return isLocalized() ? LocalizationGrant.never : localizationGrant; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; UsmUser usmUser = (UsmUser) o; if (!securityName.equals(usmUser.securityName)) return false; if (!Objects.equals(authenticationPassphrase, usmUser.authenticationPassphrase)) return false; if (!Objects.equals(privacyPassphrase, usmUser.privacyPassphrase)) return false; if (!Objects.equals(authenticationProtocol, usmUser.authenticationProtocol)) return false; if (!Objects.equals(privacyProtocol, usmUser.privacyProtocol)) return false; if (!Objects.equals(localizationEngineID, usmUser.localizationEngineID)) return false; if (!Objects.equals(localizationGrant, usmUser.localizationGrant)) return false; return true; } @Override public int hashCode() { return securityName.hashCode(); } public String toString() { return "UsmUser[secName="+securityName+ ",authProtocol="+authenticationProtocol+ ",authPassphrase="+authenticationPassphrase+ ",privProtocol="+privacyProtocol+ ",privPassphrase="+privacyPassphrase+ ",localizationEngineID="+getLocalizationEngineID()+ ",allowedLocalization="+ localizationGrant + "]"; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy