001    /*
002     * Copyright 2012-2015 UnboundID Corp.
003     * All Rights Reserved.
004     */
005    /*
006     * Copyright (C) 2015 UnboundID Corp.
007     *
008     * This program is free software; you can redistribute it and/or modify
009     * it under the terms of the GNU General Public License (GPLv2 only)
010     * or the terms of the GNU Lesser General Public License (LGPLv2.1 only)
011     * as published by the Free Software Foundation.
012     *
013     * This program is distributed in the hope that it will be useful,
014     * but WITHOUT ANY WARRANTY; without even the implied warranty of
015     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
016     * GNU General Public License for more details.
017     *
018     * You should have received a copy of the GNU General Public License
019     * along with this program; if not, see <http://www.gnu.org/licenses>.
020     */
021    package com.unboundid.ldap.sdk.unboundidds;
022    
023    
024    
025    import com.unboundid.asn1.ASN1OctetString;
026    import com.unboundid.ldap.sdk.BindResult;
027    import com.unboundid.ldap.sdk.Control;
028    import com.unboundid.ldap.sdk.InternalSDKHelper;
029    import com.unboundid.ldap.sdk.LDAPConnection;
030    import com.unboundid.ldap.sdk.LDAPException;
031    import com.unboundid.ldap.sdk.SASLBindRequest;
032    import com.unboundid.util.ThreadSafety;
033    import com.unboundid.util.ThreadSafetyLevel;
034    import com.unboundid.util.Validator;
035    
036    
037    
038    /**
039     * <BLOCKQUOTE>
040     *   <B>NOTE:</B>  This class is part of the Commercial Edition of the UnboundID
041     *   LDAP SDK for Java.  It is not available for use in applications that
042     *   include only the Standard Edition of the LDAP SDK, and is not supported for
043     *   use in conjunction with non-UnboundID products.
044     * </BLOCKQUOTE>
045     * This class provides support for an UnboundID-proprietary SASL mechanism that
046     * provides multifactor authentication using the combination of a client
047     * certificate (presented during SSL/TLS negotiation) and a static password.
048     * <BR><BR>
049     * The name for this SASL mechanism is "UNBOUNDID-CERTIFICATE-PLUS-PASSWORD".
050     * The SASL credentials consist simply of the static password for the user
051     * identified by the certificate, to make the SASL mechanism as easy as possible
052     * to use from other client APIs.
053     */
054    @ThreadSafety(level=ThreadSafetyLevel.NOT_THREADSAFE)
055    public final class UnboundIDCertificatePlusPasswordBindRequest
056           extends SASLBindRequest
057    {
058      /**
059       * The name for the UnboundID certificate plus password SASL mechanism.
060       */
061      public static final String UNBOUNDID_CERT_PLUS_PW_MECHANISM_NAME =
062           "UNBOUNDID-CERTIFICATE-PLUS-PASSWORD";
063    
064    
065    
066      /**
067       * The serial version UID for this serializable class.
068       */
069      private static final long serialVersionUID = 8863298749835036708L;
070    
071    
072    
073      // The password to use to authenticate.
074      private final ASN1OctetString password;
075    
076      // The message ID from the last LDAP message sent from this request.
077      private volatile int messageID = -1;
078    
079    
080    
081      /**
082       * Creates a new certificate plus password bind request with the provided
083       * information.
084       *
085       * @param  password  The password to use to authenticate as user identified by
086       *                   the certificate.  It must not be {@code null} or empty.
087       * @param  controls  The set of controls to include in the bind request.  It
088       *                   may be {@code null} or empty if no request controls are
089       *                   needed.
090       */
091      public UnboundIDCertificatePlusPasswordBindRequest(final String password,
092                                                         final Control... controls)
093      {
094        this(new ASN1OctetString(CRED_TYPE_SASL, password), controls);
095      }
096    
097    
098    
099      /**
100       * Creates a new certificate plus password bind request with the provided
101       * information.
102       *
103       * @param  password  The password to use to authenticate as user identified by
104       *                   the certificate.  It must not be {@code null} or empty.
105       * @param  controls  The set of controls to include in the bind request.  It
106       *                   may be {@code null} or empty if no request controls are
107       *                   needed.
108       */
109      public UnboundIDCertificatePlusPasswordBindRequest(final byte[] password,
110                                                         final Control... controls)
111      {
112        this(new ASN1OctetString(CRED_TYPE_SASL, password), controls);
113      }
114    
115    
116    
117      /**
118       * Creates a new certificate plus password bind request with the provided
119       * information.
120       *
121       * @param  password  The password to use to authenticate as user identified by
122       *                   the certificate.  It must not be {@code null} or empty.
123       * @param  controls  The set of controls to include in the bind request.  It
124       *                   may be {@code null} or empty if no request controls are
125       *                   needed.
126       */
127      private UnboundIDCertificatePlusPasswordBindRequest(
128                   final ASN1OctetString password, final Control... controls)
129      {
130        super(controls);
131    
132        Validator.ensureFalse((password.getValueLength() == 0),
133             "The bind password must not be empty");
134    
135        this.password = password;
136      }
137    
138    
139    
140      /**
141       * Retrieves the password to use to authenticate as the user identified by the
142       * certificate.
143       *
144       * @return  The password to use to authenticate as the user identified by the
145       *          certificate.
146       */
147      public ASN1OctetString getPassword()
148      {
149        return password;
150      }
151    
152    
153    
154      /**
155       * {@inheritDoc}
156       */
157      @Override()
158      public String getSASLMechanismName()
159      {
160        return UNBOUNDID_CERT_PLUS_PW_MECHANISM_NAME;
161      }
162    
163    
164    
165      /**
166       * {@inheritDoc}
167       */
168      @Override()
169      protected BindResult process(final LDAPConnection connection, final int depth)
170                throws LDAPException
171      {
172        messageID = InternalSDKHelper.nextMessageID(connection);
173        return sendBindRequest(connection, "", password, getControls(),
174             getResponseTimeoutMillis(connection));
175      }
176    
177    
178    
179      /**
180       * {@inheritDoc}
181       */
182      @Override()
183      public int getLastMessageID()
184      {
185        return messageID;
186      }
187    
188    
189    
190      /**
191       * {@inheritDoc}
192       */
193      @Override()
194      public UnboundIDCertificatePlusPasswordBindRequest duplicate()
195      {
196        return duplicate(getControls());
197      }
198    
199    
200    
201      /**
202       * {@inheritDoc}
203       */
204      @Override()
205      public UnboundIDCertificatePlusPasswordBindRequest duplicate(
206                  final Control[] controls)
207      {
208        final UnboundIDCertificatePlusPasswordBindRequest bindRequest =
209             new UnboundIDCertificatePlusPasswordBindRequest(password, controls);
210        bindRequest.setResponseTimeoutMillis(getResponseTimeoutMillis(null));
211        return bindRequest;
212      }
213    
214    
215    
216      /**
217       * {@inheritDoc}
218       */
219      @Override()
220      public UnboundIDCertificatePlusPasswordBindRequest getRebindRequest(
221                  final String host, final int port)
222      {
223        return duplicate();
224      }
225    
226    
227    
228      /**
229       * {@inheritDoc}
230       */
231      @Override()
232      public void toString(final StringBuilder buffer)
233      {
234        buffer.append("UnboundIDCertificatePlusPasswordBindRequest(");
235    
236        final Control[] controls = getControls();
237        if (controls.length > 0)
238        {
239          buffer.append("controls={");
240          for (int i=0; i < controls.length; i++)
241          {
242            if (i > 0)
243            {
244              buffer.append(", ");
245            }
246    
247            buffer.append(controls[i]);
248          }
249          buffer.append('}');
250        }
251    
252        buffer.append(')');
253      }
254    }