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

com.unboundid.ldap.protocol.BindRequestProtocolOp Maven / Gradle / Ivy

Go to download

The UnboundID LDAP SDK for Java is a fast, comprehensive, and easy-to-use Java API for communicating with LDAP directory servers and performing related tasks like reading and writing LDIF, encoding and decoding data using base64 and ASN.1 BER, and performing secure communication. This package contains the Standard Edition of the LDAP SDK, which is a complete, general-purpose library for communicating with LDAPv3 directory servers.

There is a newer version: 7.0.1
Show newest version
/*
 * Copyright 2009-2023 Ping Identity Corporation
 * All Rights Reserved.
 */
/*
 * Copyright 2009-2023 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) 2009-2023 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.protocol;



import com.unboundid.asn1.ASN1Buffer;
import com.unboundid.asn1.ASN1BufferSequence;
import com.unboundid.asn1.ASN1Element;
import com.unboundid.asn1.ASN1Integer;
import com.unboundid.asn1.ASN1OctetString;
import com.unboundid.asn1.ASN1Sequence;
import com.unboundid.asn1.ASN1StreamReader;
import com.unboundid.asn1.ASN1StreamReaderSequence;
import com.unboundid.ldap.sdk.BindRequest;
import com.unboundid.ldap.sdk.Control;
import com.unboundid.ldap.sdk.GenericSASLBindRequest;
import com.unboundid.ldap.sdk.LDAPException;
import com.unboundid.ldap.sdk.ResultCode;
import com.unboundid.ldap.sdk.SimpleBindRequest;
import com.unboundid.util.LDAPSDKUsageException;
import com.unboundid.util.Debug;
import com.unboundid.util.InternalUseOnly;
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.protocol.ProtocolMessages.*;



/**
 * This class provides an implementation of an LDAP bind request protocol op.
 */
@InternalUseOnly()
@NotMutable()
@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
public final class BindRequestProtocolOp
       implements ProtocolOp
{
  /**
   * The credentials type for simple bind requests.
   */
  public static final byte CRED_TYPE_SIMPLE = (byte) 0x80;



  /**
   * The credentials type for SASL bind requests.
   */
  public static final byte CRED_TYPE_SASL = (byte) 0xA3;



  /**
   * The serial version UID for this serializable class.
   */
  private static final long serialVersionUID = 6661208657485444954L;



  // The credentials to use for SASL authentication.
  @Nullable private final ASN1OctetString saslCredentials;

  // The password to use for simple authentication.
  @Nullable private final ASN1OctetString simplePassword;

  // The credentials type for this bind request.
  private final byte credentialsType;

  // The protocol version for this bind request.
  private final int version;

  // The bind DN to use for this bind request.
  @NotNull private final String bindDN;

  // The name of the SASL mechanism.
  @Nullable private final String saslMechanism;



  /**
   * Creates a new bind request protocol op for a simple bind.
   *
   * @param  bindDN    The DN for this bind request.
   * @param  password  The password for this bind request.
   */
  public BindRequestProtocolOp(@Nullable final String bindDN,
                               @Nullable final String password)
  {
    if (bindDN == null)
    {
      this.bindDN = "";
    }
    else
    {
      this.bindDN = bindDN;
    }

    if (password == null)
    {
      simplePassword = new ASN1OctetString(CRED_TYPE_SIMPLE);
    }
    else
    {
      simplePassword = new ASN1OctetString(CRED_TYPE_SIMPLE, password);
    }

    version         = 3;
    credentialsType = CRED_TYPE_SIMPLE;
    saslMechanism   = null;
    saslCredentials = null;
  }



  /**
   * Creates a new bind request protocol op for a simple bind.
   *
   * @param  bindDN    The DN for this bind request.
   * @param  password  The password for this bind request.
   */
  public BindRequestProtocolOp(@Nullable final String bindDN,
                               @Nullable final byte[] password)
  {
    if (bindDN == null)
    {
      this.bindDN = "";
    }
    else
    {
      this.bindDN = bindDN;
    }

    if (password == null)
    {
      simplePassword = new ASN1OctetString(CRED_TYPE_SIMPLE);
    }
    else
    {
      simplePassword = new ASN1OctetString(CRED_TYPE_SIMPLE, password);
    }

    version         = 3;
    credentialsType = CRED_TYPE_SIMPLE;
    saslMechanism   = null;
    saslCredentials = null;
  }



  /**
   * Creates a new bind request protocol op for a SASL bind.
   *
   * @param  bindDN           The DN for this bind request.
   * @param  saslMechanism    The name of the SASL mechanism for this bind
   *                          request.  It must not be {@code null}.
   * @param  saslCredentials  The SASL credentials for this bind request, if
   *                          any.
   */
  public BindRequestProtocolOp(@Nullable final String bindDN,
                               @NotNull final String saslMechanism,
                               @Nullable final ASN1OctetString saslCredentials)
  {
    this.saslMechanism   = saslMechanism;
    this.saslCredentials = saslCredentials;

    if (bindDN == null)
    {
      this.bindDN = "";
    }
    else
    {
      this.bindDN = bindDN;
    }

    version         = 3;
    credentialsType = CRED_TYPE_SASL;
    simplePassword  = null;
  }



  /**
   * Creates a new bind request protocol op from the provided bind request
   * object.
   *
   * @param  request  The simple bind request to use to create this protocol op.
   *                  It must have been created with a static password rather
   *                  than using a password provider.
   *
   * @throws  LDAPSDKUsageException  If the provided simple bind request is
   *                                 configured to use a password provider
   *                                 rather than a static password.
   */
  public BindRequestProtocolOp(@NotNull final SimpleBindRequest request)
         throws LDAPSDKUsageException
  {
    version         = 3;
    credentialsType = CRED_TYPE_SIMPLE;
    bindDN          = request.getBindDN();
    simplePassword  = request.getPassword();
    saslMechanism   = null;
    saslCredentials = null;

    if (simplePassword == null)
    {
      throw new LDAPSDKUsageException(
           ERR_BIND_REQUEST_CANNOT_CREATE_WITH_PASSWORD_PROVIDER.get());
    }
  }



  /**
   * Creates a new bind request protocol op from the provided bind request
   * object.
   *
   * @param  request  The generic SASL bind request to use to create this
   *                  protocol op.
   */
  public BindRequestProtocolOp(@NotNull final GenericSASLBindRequest request)
  {
    version         = 3;
    credentialsType = CRED_TYPE_SASL;
    bindDN          = request.getBindDN();
    simplePassword  = null;
    saslMechanism   = request.getSASLMechanismName();
    saslCredentials = request.getCredentials();
  }



  /**
   * Creates a new bind request protocol op read from the provided ASN.1 stream
   * reader.
   *
   * @param  reader  The ASN.1 stream reader from which to read the bind request
   *                 protocol op.
   *
   * @throws  LDAPException  If a problem occurs while reading or parsing the
   *                         bind request.
   */
  BindRequestProtocolOp(@NotNull final ASN1StreamReader reader)
       throws LDAPException
  {
    try
    {
      reader.beginSequence();
      version         = reader.readInteger();
      bindDN          = reader.readString();
      credentialsType = (byte) reader.peek();

      Validator.ensureNotNull(bindDN);

      switch (credentialsType)
      {
        case CRED_TYPE_SIMPLE:
          simplePassword =
               new ASN1OctetString(credentialsType, reader.readBytes());
          saslMechanism   = null;
          saslCredentials = null;
          Validator.ensureNotNull(bindDN);
          break;

        case CRED_TYPE_SASL:
          final ASN1StreamReaderSequence saslSequence = reader.beginSequence();
          saslMechanism = reader.readString();
          Validator.ensureNotNull(saslMechanism);
          if (saslSequence.hasMoreElements())
          {
            saslCredentials = new ASN1OctetString(reader.readBytes());
          }
          else
          {
            saslCredentials = null;
          }
          simplePassword = null;
          break;

        default:
          throw new LDAPException(ResultCode.DECODING_ERROR,
               ERR_BIND_REQUEST_INVALID_CRED_TYPE.get(
                    StaticUtils.toHex(credentialsType)));
      }
    }
    catch (final LDAPException le)
    {
      Debug.debugException(le);
      throw le;
    }
    catch (final Exception e)
    {
      Debug.debugException(e);

      throw new LDAPException(ResultCode.DECODING_ERROR,
           ERR_BIND_REQUEST_CANNOT_DECODE.get(
                StaticUtils.getExceptionMessage(e)),
           e);
    }
  }



  /**
   * Creates a new bind request protocol op with the provided information.
   *
   * @param  version          The protocol version.
   * @param  bindDN           The bind DN.  It must not be {@code null} (but may
   *                          be empty).
   * @param  credentialsType  The type of credentials supplied.
   * @param  simplePassword   The password for simple authentication, if
   *                          appropriate.
   * @param  saslMechanism    The name of the SASL mechanism, if appropriate.
   * @param  saslCredentials  The SASL credentials, if appropriate.
   */
  private BindRequestProtocolOp(final int version, @NotNull final String bindDN,
                                final byte credentialsType,
                                @Nullable final ASN1OctetString simplePassword,
                                @Nullable final String saslMechanism,
                                @Nullable final ASN1OctetString saslCredentials)
  {
    this.version         = version;
    this.bindDN          = bindDN;
    this.credentialsType = credentialsType;
    this.simplePassword  = simplePassword;
    this.saslMechanism   = saslMechanism;
    this.saslCredentials = saslCredentials;
  }



  /**
   * Retrieves the protocol version for this bind request.
   *
   * @return  The protocol version for this bind request.
   */
  public int getVersion()
  {
    return version;
  }



  /**
   * Retrieves the bind DN for this bind request.
   *
   * @return  The bind DN for this bind request, or an empty string if none was
   *          provided.
   */
  @NotNull()
  public String getBindDN()
  {
    return bindDN;
  }



  /**
   * Retrieves the credentials type for this bind request.  It will either be
   * {@link #CRED_TYPE_SIMPLE} or {@link #CRED_TYPE_SASL}.
   *
   * @return  The credentials type for this bind request.
   */
  public byte getCredentialsType()
  {
    return credentialsType;
  }



  /**
   * Retrieves the password to use for simple authentication.
   *
   * @return  The password to use for simple authentication, or {@code null} if
   *          SASL authentication will be used.
   */
  @Nullable()
  public ASN1OctetString getSimplePassword()
  {
    return simplePassword;
  }



  /**
   * Retrieves the name of the SASL mechanism for this bind request.
   *
   * @return  The name of the SASL mechanism for this bind request, or
   *          {@code null} if simple authentication will be used.
   */
  @Nullable()
  public String getSASLMechanism()
  {
    return saslMechanism;
  }



  /**
   * Retrieves the credentials to use for SASL authentication, if any.
   *
   * @return  The credentials to use for SASL authentication, or {@code null} if
   *          there are no SASL credentials or if simple authentication will be
   *          used.
   */
  @Nullable()
  public ASN1OctetString getSASLCredentials()
  {
    return saslCredentials;
  }



  /**
   * {@inheritDoc}
   */
  @Override()
  public byte getProtocolOpType()
  {
    return LDAPMessage.PROTOCOL_OP_TYPE_BIND_REQUEST;
  }



  /**
   * {@inheritDoc}
   */
  @Override()
  @NotNull()
  public ASN1Element encodeProtocolOp()
  {
    final ASN1Element credentials;
    if (credentialsType == CRED_TYPE_SIMPLE)
    {
      credentials = simplePassword;
    }
    else
    {
      if (saslCredentials == null)
      {
        credentials = new ASN1Sequence(CRED_TYPE_SASL,
             new ASN1OctetString(saslMechanism));
      }
      else
      {
        credentials = new ASN1Sequence(CRED_TYPE_SASL,
             new ASN1OctetString(saslMechanism),
             saslCredentials);
      }
    }

    return new ASN1Sequence(LDAPMessage.PROTOCOL_OP_TYPE_BIND_REQUEST,
         new ASN1Integer(version),
         new ASN1OctetString(bindDN),
         credentials);
  }



  /**
   * Decodes the provided ASN.1 element as a bind request protocol op.
   *
   * @param  element  The ASN.1 element to be decoded.
   *
   * @return  The decoded bind request protocol op.
   *
   * @throws  LDAPException  If the provided ASN.1 element cannot be decoded as
   *                         a bind request protocol op.
   */
  @NotNull()
  public static BindRequestProtocolOp decodeProtocolOp(
                                           @NotNull final ASN1Element element)
         throws LDAPException
  {
    try
    {
      final ASN1Element[] elements =
           ASN1Sequence.decodeAsSequence(element).elements();
      final int version = ASN1Integer.decodeAsInteger(elements[0]).intValue();
      final String bindDN =
           ASN1OctetString.decodeAsOctetString(elements[1]).stringValue();

      final ASN1OctetString saslCredentials;
      final ASN1OctetString simplePassword;
      final String saslMechanism;
      switch (elements[2].getType())
      {
        case CRED_TYPE_SIMPLE:
          simplePassword  = ASN1OctetString.decodeAsOctetString(elements[2]);
          saslMechanism   = null;
          saslCredentials = null;
          break;

        case CRED_TYPE_SASL:
          final ASN1Element[] saslElements =
               ASN1Sequence.decodeAsSequence(elements[2]).elements();
          saslMechanism = ASN1OctetString.decodeAsOctetString(saslElements[0]).
               stringValue();
          if (saslElements.length == 1)
          {
            saslCredentials = null;
          }
          else
          {
            saslCredentials =
                 ASN1OctetString.decodeAsOctetString(saslElements[1]);
          }

          simplePassword = null;
          break;

        default:
          throw new LDAPException(ResultCode.DECODING_ERROR,
               ERR_BIND_REQUEST_INVALID_CRED_TYPE.get(
                    StaticUtils.toHex(elements[2].getType())));
      }

      return new BindRequestProtocolOp(version, bindDN, elements[2].getType(),
           simplePassword, saslMechanism, saslCredentials);
    }
    catch (final LDAPException le)
    {
      Debug.debugException(le);
      throw le;
    }
    catch (final Exception e)
    {
      Debug.debugException(e);
      throw new LDAPException(ResultCode.DECODING_ERROR,
           ERR_BIND_REQUEST_CANNOT_DECODE.get(
                StaticUtils.getExceptionMessage(e)),
           e);
    }
  }



  /**
   * {@inheritDoc}
   */
  @Override()
  public void writeTo(@NotNull final ASN1Buffer buffer)
  {
    final ASN1BufferSequence opSequence =
         buffer.beginSequence(LDAPMessage.PROTOCOL_OP_TYPE_BIND_REQUEST);
    buffer.addInteger(version);
    buffer.addOctetString(bindDN);

    if (credentialsType == CRED_TYPE_SIMPLE)
    {
      buffer.addElement(simplePassword);
    }
    else
    {
      final ASN1BufferSequence saslSequence =
           buffer.beginSequence(CRED_TYPE_SASL);
      buffer.addOctetString(saslMechanism);
      if (saslCredentials != null)
      {
        buffer.addElement(saslCredentials);
      }
      saslSequence.end();
    }
    opSequence.end();
    buffer.setZeroBufferOnClear();
  }



  /**
   * Creates a new bind request object from this bind request protocol op.
   *
   * @param  controls  The set of controls to include in the bind request.  It
   *                   may be empty or {@code null} if no controls should be
   *                   included.
   *
   * @return  The bind request that was created.
   */
  @NotNull()
  public BindRequest toBindRequest(@Nullable final Control... controls)
  {
    if (credentialsType == CRED_TYPE_SIMPLE)
    {
      return new SimpleBindRequest(bindDN, simplePassword.getValue(),
           controls);
    }
    else
    {
      return new GenericSASLBindRequest(bindDN, saslMechanism,
           saslCredentials, controls);
    }
  }



  /**
   * Retrieves a string representation of this protocol op.
   *
   * @return  A string representation of this protocol op.
   */
  @Override()
  @NotNull()
  public String toString()
  {
    final StringBuilder buffer = new StringBuilder();
    toString(buffer);
    return buffer.toString();
  }



  /**
   * {@inheritDoc}
   */
  @Override()
  public void toString(@NotNull final StringBuilder buffer)
  {
    buffer.append("BindRequestProtocolOp(version=");
    buffer.append(version);
    buffer.append(", bindDN='");
    buffer.append(bindDN);
    buffer.append("', type=");

    if (credentialsType == CRED_TYPE_SIMPLE)
    {
      buffer.append("simple");
    }
    else
    {
      buffer.append("SASL, mechanism=");
      buffer.append(saslMechanism);
    }

    buffer.append(')');
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy