Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright 2016-2024 Ping Identity Corporation
* All Rights Reserved.
*/
/*
* Copyright 2016-2024 Ping Identity Corporation
*
* 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.
*/
/*
* Copyright (C) 2016-2024 Ping Identity Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License (GPLv2 only)
* or the terms of the GNU Lesser General Public License (LGPLv2.1 only)
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see .
*/
package com.unboundid.ldap.sdk.unboundidds;
import java.util.ArrayList;
import java.util.List;
import com.unboundid.asn1.ASN1Element;
import com.unboundid.asn1.ASN1OctetString;
import com.unboundid.asn1.ASN1Sequence;
import com.unboundid.ldap.sdk.BindResult;
import com.unboundid.ldap.sdk.Control;
import com.unboundid.ldap.sdk.InternalSDKHelper;
import com.unboundid.ldap.sdk.LDAPConnection;
import com.unboundid.ldap.sdk.LDAPException;
import com.unboundid.ldap.sdk.ResultCode;
import com.unboundid.ldap.sdk.SASLBindRequest;
import com.unboundid.ldap.sdk.ToCodeArgHelper;
import com.unboundid.ldap.sdk.ToCodeHelper;
import com.unboundid.ldap.sdk.unboundidds.extensions.
DeregisterYubiKeyOTPDeviceExtendedRequest;
import com.unboundid.ldap.sdk.unboundidds.extensions.
RegisterYubiKeyOTPDeviceExtendedRequest;
import com.unboundid.util.Debug;
import com.unboundid.util.NotMutable;
import com.unboundid.util.NotNull;
import com.unboundid.util.Nullable;
import com.unboundid.util.StaticUtils;
import com.unboundid.util.ThreadSafety;
import com.unboundid.util.ThreadSafetyLevel;
import com.unboundid.util.Validator;
import static com.unboundid.ldap.sdk.unboundidds.UnboundIDDSMessages.*;
/**
* This class provides an implementation of a SASL bind request that may be used
* to authenticate to a Directory Server using the UNBOUNDID-YUBIKEY-OTP
* mechanism. The credentials include at least an authentication ID and a
* one-time password generated by a YubiKey device. The request may also
* include a static password (which may or may not be required by the server)
* and an optional authorization ID.
*
*
* NOTE: This class, and other classes within the
* {@code com.unboundid.ldap.sdk.unboundidds} package structure, are only
* supported for use against Ping Identity, UnboundID, and
* Nokia/Alcatel-Lucent 8661 server products. These classes provide support
* for proprietary functionality or for external specifications that are not
* considered stable or mature enough to be guaranteed to work in an
* interoperable way with other types of LDAP servers.
*
*
* The UNBOUNDID-YUBIKEY-OTP bind request MUST include SASL credentials with the
* following ASN.1 encoding:
*
*
*
* @see RegisterYubiKeyOTPDeviceExtendedRequest
* @see DeregisterYubiKeyOTPDeviceExtendedRequest
*/
@NotMutable()
@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
public final class UnboundIDYubiKeyOTPBindRequest
extends SASLBindRequest
{
/**
* The name for the UnboundID YubiKey SASL mechanism.
*/
@NotNull public static final String UNBOUNDID_YUBIKEY_OTP_MECHANISM_NAME =
"UNBOUNDID-YUBIKEY-OTP";
/**
* The BER type for the authentication ID element of the credentials sequence.
*/
private static final byte TYPE_AUTHENTICATION_ID = (byte) 0x80;
/**
* The BER type for the authorization ID element of the credentials sequence.
*/
private static final byte TYPE_AUTHORIZATION_ID = (byte) 0x81;
/**
* The BER type for the static password element of the credentials sequence.
*/
private static final byte TYPE_STATIC_PASSWORD = (byte) 0x82;
/**
* The BER type for the YubiKey OTP element of the credentials sequence.
*/
private static final byte TYPE_YUBIKEY_OTP = (byte) 0x83;
/**
* The serial version UID for this serializable class.
*/
private static final long serialVersionUID = -6124016046606933247L;
// The static password for the user, if provided.
@Nullable private final ASN1OctetString staticPassword;
// The message ID from the last LDAP message sent from this request.
private volatile int messageID = -1;
// The authentication ID for the user.
@NotNull private final String authenticationID;
// The authorization ID for the bind request, if provided.
@Nullable private final String authorizationID;
// The one-time password generated by a YubiKey device.
@NotNull private final String yubiKeyOTP;
/**
* Creates a new UNBOUNDID-YUBIKEY-OTP bind request with the provided
* information.
*
* @param authenticationID The authentication ID for the bind request. It
* must not be {@code null}, and must have the form
* "dn:" followed by the DN of the target user or
* "u:" followed by the the username of the target
* user.
* @param authorizationID The authorization ID for the bind request. It
* may be {@code null} if the authorization identity
* should be the same as the authentication
* identity.
* @param staticPassword The static password for the user specified as the
* authentication identity. It may be {@code null}
* if authentication should be performed using only
* the YubiKey OTP.
* @param yubiKeyOTP The one-time password generated by the YubiKey
* device. It must not be {@code null}.
* @param controls The set of controls to include in the bind
* request. It may be {@code null} or empty if
* there should not be any request controls.
*/
public UnboundIDYubiKeyOTPBindRequest(@NotNull final String authenticationID,
@Nullable final String authorizationID,
@Nullable final String staticPassword,
@NotNull final String yubiKeyOTP,
@Nullable final Control... controls)
{
this(authenticationID, authorizationID, toASN1OctetString(staticPassword),
yubiKeyOTP, controls);
}
/**
* Creates a new UNBOUNDID-YUBIKEY-OTP bind request with the provided
* information.
*
* @param authenticationID The authentication ID for the bind request. It
* must not be {@code null}, and must have the form
* "dn:" followed by the DN of the target user or
* "u:" followed by the the username of the target
* user.
* @param authorizationID The authorization ID for the bind request. It
* may be {@code null} if the authorization identity
* should be the same as the authentication
* identity.
* @param staticPassword The static password for the user specified as the
* authentication identity. It may be {@code null}
* if authentication should be performed using only
* the YubiKey OTP.
* @param yubiKeyOTP The one-time password generated by the YubiKey
* device. It must not be {@code null}.
* @param controls The set of controls to include in the bind
* request. It may be {@code null} or empty if
* there should not be any request controls.
*/
public UnboundIDYubiKeyOTPBindRequest(@NotNull final String authenticationID,
@Nullable final String authorizationID,
@Nullable final byte[] staticPassword,
@NotNull final String yubiKeyOTP,
@Nullable final Control... controls)
{
this(authenticationID, authorizationID, toASN1OctetString(staticPassword),
yubiKeyOTP, controls);
}
/**
* Creates a new UNBOUNDID-YUBIKEY-OTP bind request with the provided
* information.
*
* @param authenticationID The authentication ID for the bind request. It
* must not be {@code null}, and must have the form
* "dn:" followed by the DN of the target user or
* "u:" followed by the the username of the target
* user.
* @param authorizationID The authorization ID for the bind request. It
* may be {@code null} if the authorization identity
* should be the same as the authentication
* identity.
* @param staticPassword The static password for the user specified as the
* authentication identity. It may be {@code null}
* if authentication should be performed using only
* the YubiKey OTP.
* @param yubiKeyOTP The one-time password generated by the YubiKey
* device. It must not be {@code null}.
* @param controls The set of controls to include in the bind
* request. It may be {@code null} or empty if
* there should not be any request controls.
*/
private UnboundIDYubiKeyOTPBindRequest(@NotNull final String authenticationID,
@Nullable final String authorizationID,
@Nullable final ASN1OctetString staticPassword,
@NotNull final String yubiKeyOTP,
@Nullable final Control... controls)
{
super(controls);
Validator.ensureNotNull(authenticationID);
Validator.ensureNotNull(yubiKeyOTP);
this.authenticationID = authenticationID;
this.authorizationID = authorizationID;
this.staticPassword = staticPassword;
this.yubiKeyOTP = yubiKeyOTP;
}
/**
* Retrieves an ASN.1 octet string that represents the appropriate encoding
* for the provided password.
*
* @param password The password object to convert to an ASN.1 octet string.
* It may be {@code null} if no static password is required.
* Otherwise, it must either be a string or a byte array.
*
* @return The ASN.1 octet string created from the provided password object,
* or {@code null} if the provided password object was null.
*/
@Nullable()
private static ASN1OctetString toASN1OctetString(
@Nullable final Object password)
{
if (password == null)
{
return null;
}
else if (password instanceof byte[])
{
return new ASN1OctetString(TYPE_STATIC_PASSWORD, (byte[]) password);
}
else
{
return new ASN1OctetString(TYPE_STATIC_PASSWORD,
String.valueOf(password));
}
}
/**
* Creates a new UNBOUNDID-YUBIKEY-OTP SASL bind request decoded from the
* provided SASL credentials.
*
* @param saslCredentials The SASL credentials to decode in order to create
* the UNBOUNDID-YUBIKEY-OTP SASL bind request. It
* must not be {@code null}.
* @param controls The set of controls to include in the bind
* request. This may be {@code null} or empty if no
* controls should be included in the request.
*
* @return The UNBOUNDID-YUBIKEY-OTP SASL bind request decoded from the
* provided credentials.
*
* @throws LDAPException If the provided credentials cannot be decoded to a
* valid UNBOUNDID-YUBIKEY-OTP bind request.
*/
@NotNull()
public static UnboundIDYubiKeyOTPBindRequest decodeCredentials(
@NotNull final ASN1OctetString saslCredentials,
@Nullable final Control... controls)
throws LDAPException
{
try
{
ASN1OctetString staticPassword = null;
String authenticationID = null;
String authorizationID = null;
String yubiKeyOTP = null;
for (final ASN1Element e :
ASN1Sequence.decodeAsSequence(saslCredentials.getValue()).elements())
{
switch (e.getType())
{
case TYPE_AUTHENTICATION_ID:
authenticationID =
ASN1OctetString.decodeAsOctetString(e).stringValue();
break;
case TYPE_AUTHORIZATION_ID:
authorizationID =
ASN1OctetString.decodeAsOctetString(e).stringValue();
break;
case TYPE_STATIC_PASSWORD:
staticPassword = ASN1OctetString.decodeAsOctetString(e);
break;
case TYPE_YUBIKEY_OTP:
yubiKeyOTP = ASN1OctetString.decodeAsOctetString(e).stringValue();
break;
default:
throw new LDAPException(ResultCode.DECODING_ERROR,
ERR_YUBIKEY_OTP_DECODE_UNRECOGNIZED_CRED_ELEMENT.get(
UNBOUNDID_YUBIKEY_OTP_MECHANISM_NAME,
StaticUtils.toHex(e.getType())));
}
}
if (authenticationID == null)
{
throw new LDAPException(ResultCode.DECODING_ERROR,
ERR_YUBIKEY_OTP_DECODE_NO_AUTH_ID.get(
UNBOUNDID_YUBIKEY_OTP_MECHANISM_NAME));
}
if (yubiKeyOTP == null)
{
throw new LDAPException(ResultCode.DECODING_ERROR,
ERR_YUBIKEY_OTP_NO_OTP.get(UNBOUNDID_YUBIKEY_OTP_MECHANISM_NAME));
}
return new UnboundIDYubiKeyOTPBindRequest(authenticationID,
authorizationID, staticPassword, yubiKeyOTP, controls);
}
catch (final LDAPException le)
{
Debug.debugException(le);
throw le;
}
catch (final Exception e)
{
Debug.debugException(e);
throw new LDAPException(ResultCode.DECODING_ERROR,
ERR_YUBIKEY_OTP_DECODE_ERROR.get(
UNBOUNDID_YUBIKEY_OTP_MECHANISM_NAME,
StaticUtils.getExceptionMessage(e)),
e);
}
}
/**
* Retrieves the authentication ID for the bind request.
*
* @return The authentication ID for the bind request.
*/
@NotNull()
public String getAuthenticationID()
{
return authenticationID;
}
/**
* Retrieves the authorization ID for the bind request, if any.
*
* @return The authorization ID for the bind request, or {@code null} if the
* authorization identity should match the authentication identity.
*/
@Nullable()
public String getAuthorizationID()
{
return authorizationID;
}
/**
* Retrieves the string representation of the static password for the bind
* request, if any.
*
* @return The string representation of the static password for the bind
* request, or {@code null} if there is no static password.
*/
@Nullable()
public String getStaticPasswordString()
{
if (staticPassword == null)
{
return null;
}
else
{
return staticPassword.stringValue();
}
}
/**
* Retrieves the bytes that comprise the static password for the bind request,
* if any.
*
* @return The bytes that comprise the static password for the bind request,
* or {@code null} if there is no static password.
*/
@Nullable()
public byte[] getStaticPasswordBytes()
{
if (staticPassword == null)
{
return null;
}
else
{
return staticPassword.getValue();
}
}
/**
* Retrieves the YubiKey-generated one-time password to include in the bind
* request.
*
* @return The YubiKey-generated one-time password to include in the bind
* request.
*/
@NotNull()
public String getYubiKeyOTP()
{
return yubiKeyOTP;
}
/**
* Sends this bind request to the target server over the provided connection
* and returns the corresponding response.
*
* @param connection The connection to use to send this bind request to the
* server and read the associated response.
* @param depth The current referral depth for this request. It should
* always be one for the initial request, and should only
* be incremented when following referrals.
*
* @return The bind response read from the server.
*
* @throws LDAPException If a problem occurs while sending the request or
* reading the response.
*/
@Override()
@NotNull()
protected BindResult process(@NotNull final LDAPConnection connection,
final int depth)
throws LDAPException
{
setReferralDepth(depth);
messageID = InternalSDKHelper.nextMessageID(connection);
return sendBindRequest(connection, "", encodeCredentials(), getControls(),
getResponseTimeoutMillis(connection));
}
/**
* Retrieves an ASN.1 octet string containing the encoded credentials for this
* bind request.
*
* @return An ASN.1 octet string containing the encoded credentials for this
* bind request.
*/
@NotNull()
public ASN1OctetString encodeCredentials()
{
return encodeCredentials(authenticationID, authorizationID, staticPassword,
yubiKeyOTP);
}
/**
* Encodes the provided information into an ASN.1 octet string suitable for
* use as the SASL credentials for an UNBOUNDID-YUBIKEY-OTP bind request.
*
* @param authenticationID The authentication ID for the bind request. It
* must not be {@code null}, and must have the form
* "dn:" followed by the DN of the target user or
* "u:" followed by the the username of the target
* user.
* @param authorizationID The authorization ID for the bind request. It
* may be {@code null} if the authorization identity
* should be the same as the authentication
* identity.
* @param staticPassword The static password for the user specified as the
* authentication identity. It may be {@code null}
* if authentication should be performed using only
* the YubiKey OTP.
* @param yubiKeyOTP The one-time password generated by the YubiKey
* device. It must not be {@code null}.
*
* @return An ASN.1 octet string suitable for use as the SASL credentials for
* an UNBOUNDID-YUBIKEY-OTP bind request.
*/
@NotNull()
public static ASN1OctetString encodeCredentials(
@NotNull final String authenticationID,
@Nullable final String authorizationID,
@Nullable final ASN1OctetString staticPassword,
@NotNull final String yubiKeyOTP)
{
Validator.ensureNotNull(authenticationID);
Validator.ensureNotNull(yubiKeyOTP);
final ArrayList elements = new ArrayList<>(4);
elements.add(new ASN1OctetString(TYPE_AUTHENTICATION_ID, authenticationID));
if (authorizationID != null)
{
elements.add(new ASN1OctetString(TYPE_AUTHORIZATION_ID, authorizationID));
}
if (staticPassword != null)
{
elements.add(new ASN1OctetString(TYPE_STATIC_PASSWORD,
staticPassword.getValue()));
}
elements.add(new ASN1OctetString(TYPE_YUBIKEY_OTP, yubiKeyOTP));
return new ASN1OctetString(new ASN1Sequence(elements).encode());
}
/**
* {@inheritDoc}
*/
@Override()
@NotNull()
public UnboundIDYubiKeyOTPBindRequest duplicate()
{
return duplicate(getControls());
}
/**
* {@inheritDoc}
*/
@Override()
@NotNull()
public UnboundIDYubiKeyOTPBindRequest duplicate(
@Nullable final Control[] controls)
{
final UnboundIDYubiKeyOTPBindRequest bindRequest =
new UnboundIDYubiKeyOTPBindRequest(authenticationID, authorizationID,
staticPassword, yubiKeyOTP, controls);
bindRequest.setResponseTimeoutMillis(getResponseTimeoutMillis(null));
bindRequest.setIntermediateResponseListener(
getIntermediateResponseListener());
bindRequest.setReferralDepth(getReferralDepth());
bindRequest.setReferralConnector(getReferralConnectorInternal());
return bindRequest;
}
/**
* {@inheritDoc}
*/
@Override()
@NotNull()
public String getSASLMechanismName()
{
return UNBOUNDID_YUBIKEY_OTP_MECHANISM_NAME;
}
/**
* {@inheritDoc}
*/
@Override()
public int getLastMessageID()
{
return messageID;
}
/**
* {@inheritDoc}
*/
@Override()
public void toString(@NotNull final StringBuilder buffer)
{
buffer.append("UnboundYubiKeyOTPBindRequest(authenticationID='");
buffer.append(authenticationID);
if (authorizationID != null)
{
buffer.append("', authorizationID='");
buffer.append(authorizationID);
}
buffer.append("', staticPasswordProvided=");
buffer.append(staticPassword != null);
final Control[] controls = getControls();
if (controls.length > 0)
{
buffer.append(", controls={");
for (int i=0; i < controls.length; i++)
{
if (i > 0)
{
buffer.append(", ");
}
buffer.append(controls[i]);
}
buffer.append('}');
}
buffer.append(')');
}
/**
* {@inheritDoc}
*/
@Override()
public void toCode(@NotNull final List lineList,
@NotNull final String requestID,
final int indentSpaces, final boolean includeProcessing)
{
// Create the request variable.
final ArrayList constructorArgs = new ArrayList<>(5);
constructorArgs.add(ToCodeArgHelper.createString(getAuthenticationID(),
"Authentication ID"));
constructorArgs.add(ToCodeArgHelper.createString(getAuthorizationID(),
"Authorization ID"));
constructorArgs.add(ToCodeArgHelper.createString(
"---redacted-static-password---", "Static Password"));
constructorArgs.add(ToCodeArgHelper.createString(
((getStaticPasswordString() == null)
? "null"
: "---redacted-static-password---"),
"Static Password"));
constructorArgs.add(ToCodeArgHelper.createString(
"---redacted-yubikey-otp---", "YubiKey OTP"));
final Control[] controls = getControls();
if (controls.length > 0)
{
constructorArgs.add(ToCodeArgHelper.createControlArray(controls,
"Bind Controls"));
}
ToCodeHelper.generateMethodCall(lineList, indentSpaces,
"UnboundIDYubiKeyOTPBindRequest", requestID + "Request",
"new UnboundIDYubiKeyOTPBindRequest", constructorArgs);
// Add lines for processing the request and obtaining the result.
if (includeProcessing)
{
// Generate a string with the appropriate indent.
final StringBuilder buffer = new StringBuilder();
for (int i=0; i < indentSpaces; i++)
{
buffer.append(' ');
}
final String indent = buffer.toString();
lineList.add("");
lineList.add(indent + "try");
lineList.add(indent + '{');
lineList.add(indent + " BindResult " + requestID +
"Result = connection.bind(" + requestID + "Request);");
lineList.add(indent + " // The bind was processed successfully.");
lineList.add(indent + '}');
lineList.add(indent + "catch (LDAPException e)");
lineList.add(indent + '{');
lineList.add(indent + " // The bind failed. Maybe the following will " +
"help explain why.");
lineList.add(indent + " // Note that the connection is now likely in " +
"an unauthenticated state.");
lineList.add(indent + " ResultCode resultCode = e.getResultCode();");
lineList.add(indent + " String message = e.getMessage();");
lineList.add(indent + " String matchedDN = e.getMatchedDN();");
lineList.add(indent + " String[] referralURLs = e.getReferralURLs();");
lineList.add(indent + " Control[] responseControls = " +
"e.getResponseControls();");
lineList.add(indent + '}');
}
}
}