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-2018 Ping Identity Corporation
 * All Rights Reserved.
 */
/*
 * Copyright (C) 2009-2018 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.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.
  private final ASN1OctetString saslCredentials;

  // The password to use for simple authentication.
  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.
  private final String bindDN;

  // The name of the SASL mechanism.
  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(final String bindDN, 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(final String bindDN, 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(final String bindDN, final String saslMechanism,
                               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(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(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(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, final String bindDN,
                                final byte credentialsType,
                                final ASN1OctetString simplePassword,
                                final String saslMechanism,
                                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.
   */
  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.
   */
  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.
   */
  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.
   */
  public ASN1OctetString getSASLCredentials()
  {
    return saslCredentials;
  }



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



  /**
   * {@inheritDoc}
   */
  @Override()
  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.
   */
  public static BindRequestProtocolOp decodeProtocolOp(
                                           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(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.
   */
  public BindRequest toBindRequest(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()
  public String toString()
  {
    final StringBuilder buffer = new StringBuilder();
    toString(buffer);
    return buffer.toString();
  }



  /**
   * {@inheritDoc}
   */
  @Override()
  public void toString(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