001 /*
002 * Copyright 2011-2016 UnboundID Corp.
003 * All Rights Reserved.
004 */
005 /*
006 * Copyright (C) 2011-2016 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;
022
023
024
025 import java.util.ArrayList;
026 import java.util.List;
027
028 import com.unboundid.asn1.ASN1OctetString;
029 import com.unboundid.util.NotMutable;
030 import com.unboundid.util.ThreadSafety;
031 import com.unboundid.util.ThreadSafetyLevel;
032 import com.unboundid.util.Validator;
033
034
035
036 /**
037 * This class provides a mechanism for performing SASL authentication in a
038 * generic manner. The caller is responsible for properly encoding the
039 * credentials (if any) and interpreting the result. Further, if the requested
040 * SASL mechanism is one that requires multiple stages, then the caller is
041 * responsible for all processing in each stage.
042 */
043 @NotMutable()
044 @ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
045 public final class GenericSASLBindRequest
046 extends SASLBindRequest
047 {
048 /**
049 * The serial version UID for this serializable class.
050 */
051 private static final long serialVersionUID = 7740968332104559230L;
052
053
054
055 // The SASL credentials that should be used for the bind request.
056 private final ASN1OctetString credentials;
057
058 // The bind DN to use for the bind request.
059 private final String bindDN;
060
061 // The name of the SASL mechanism that should be used for the bind request.
062 private final String mechanism;
063
064
065
066 /**
067 * Creates a new generic SASL bind request with the provided information.
068 *
069 * @param bindDN The bind DN that should be used for the request. It
070 * may be {@code null} if the target identity should be
071 * derived from the credentials or some other source.
072 * @param mechanism The name of the mechanism that should be used for the
073 * SASL bind. It must not be {@code null}.
074 * @param credentials The credentials that should be used for the SASL bind.
075 * It may be {@code null} if no credentials should be
076 * used.
077 * @param controls The set of controls to include in the SASL bind
078 * request. It may be {@code null} or empty if no
079 * request controls are needed.
080 */
081 public GenericSASLBindRequest(final String bindDN, final String mechanism,
082 final ASN1OctetString credentials,
083 final Control... controls)
084 {
085 super(controls);
086
087 Validator.ensureNotNull(mechanism);
088
089 this.bindDN = bindDN;
090 this.mechanism = mechanism;
091 this.credentials = credentials;
092 }
093
094
095
096 /**
097 * Retrieves the bind DN for this SASL bind request, if any.
098 *
099 * @return The bind DN for this SASL bind request, or {@code null} if the
100 * target identity should be determined from the credentials or some
101 * other mechanism.
102 */
103 public String getBindDN()
104 {
105 return bindDN;
106 }
107
108
109
110 /**
111 * {@inheritDoc}
112 */
113 @Override()
114 public String getSASLMechanismName()
115 {
116 return mechanism;
117 }
118
119
120
121 /**
122 * Retrieves the credentials for the SASL bind request, if any.
123 *
124 * @return The credentials for the SASL bind request, or {@code null} if
125 * there are none.
126 */
127 public ASN1OctetString getCredentials()
128 {
129 return credentials;
130 }
131
132
133
134 /**
135 * {@inheritDoc}
136 */
137 @Override()
138 protected BindResult process(final LDAPConnection connection, final int depth)
139 throws LDAPException
140 {
141 return sendBindRequest(connection, bindDN, credentials, getControls(),
142 getResponseTimeoutMillis(connection));
143 }
144
145
146
147 /**
148 * {@inheritDoc}
149 */
150 @Override()
151 public GenericSASLBindRequest duplicate()
152 {
153 return duplicate(getControls());
154 }
155
156
157
158 /**
159 * {@inheritDoc}
160 */
161 @Override()
162 public GenericSASLBindRequest duplicate(final Control[] controls)
163 {
164 return new GenericSASLBindRequest(bindDN, mechanism, credentials,
165 controls);
166 }
167
168
169
170 /**
171 * {@inheritDoc}
172 */
173 @Override()
174 public void toString(final StringBuilder buffer)
175 {
176 buffer.append("GenericSASLBindRequest(mechanism='");
177 buffer.append(mechanism);
178 buffer.append('\'');
179
180 if (bindDN != null)
181 {
182 buffer.append(", bindDN='");
183 buffer.append(bindDN);
184 buffer.append('\'');
185 }
186
187 if (credentials != null)
188 {
189 buffer.append(", credentials=byte[");
190 buffer.append(credentials.getValueLength());
191 buffer.append(']');
192 }
193
194 final Control[] controls = getControls();
195 if (controls.length > 0)
196 {
197 buffer.append(", controls={");
198 for (int i=0; i < controls.length; i++)
199 {
200 if (i > 0)
201 {
202 buffer.append(", ");
203 }
204
205 buffer.append(controls[i]);
206 }
207 buffer.append('}');
208 }
209
210 buffer.append(')');
211 }
212
213
214
215 /**
216 * {@inheritDoc}
217 */
218 @Override()
219 public void toCode(final List<String> lineList, final String requestID,
220 final int indentSpaces, final boolean includeProcessing)
221 {
222 // Create the request variable.
223 final ArrayList<ToCodeArgHelper> constructorArgs =
224 new ArrayList<ToCodeArgHelper>(4);
225 constructorArgs.add(ToCodeArgHelper.createString(bindDN, "Bind DN"));
226 constructorArgs.add(ToCodeArgHelper.createString(mechanism,
227 "SASL Mechanism Name"));
228 constructorArgs.add(ToCodeArgHelper.createByteArray(
229 "---redacted-SASL-credentials".getBytes(), true,
230 "SASL Credentials"));
231
232 final Control[] controls = getControls();
233 if (controls.length > 0)
234 {
235 constructorArgs.add(ToCodeArgHelper.createControlArray(controls,
236 "Bind Controls"));
237 }
238
239 ToCodeHelper.generateMethodCall(lineList, indentSpaces,
240 "GenericSASLBindRequest", requestID + "Request",
241 "new GenericSASLBindRequest", constructorArgs);
242
243
244 // Add lines for processing the request and obtaining the result.
245 if (includeProcessing)
246 {
247 // Generate a string with the appropriate indent.
248 final StringBuilder buffer = new StringBuilder();
249 for (int i=0; i < indentSpaces; i++)
250 {
251 buffer.append(' ');
252 }
253 final String indent = buffer.toString();
254
255 lineList.add("");
256 lineList.add(indent + '{');
257 lineList.add(indent + " BindResult " + requestID +
258 "Result = connection.bind(" + requestID + "Request);");
259 lineList.add(indent + " // The bind was processed successfully.");
260 lineList.add(indent + '}');
261 lineList.add(indent + "catch (SASLBindInProgressException e)");
262 lineList.add(indent + '{');
263 lineList.add(indent + " // The SASL bind requires multiple stages. " +
264 "Continue it here.");
265 lineList.add(indent + " // Do not attempt to use the connection for " +
266 "any other purpose until bind processing has completed.");
267 lineList.add(indent + '}');
268 lineList.add(indent + "catch (LDAPException e)");
269 lineList.add(indent + '{');
270 lineList.add(indent + " // The bind failed. Maybe the following will " +
271 "help explain why.");
272 lineList.add(indent + " // Note that the connection is now likely in " +
273 "an unauthenticated state.");
274 lineList.add(indent + " ResultCode resultCode = e.getResultCode();");
275 lineList.add(indent + " String message = e.getMessage();");
276 lineList.add(indent + " String matchedDN = e.getMatchedDN();");
277 lineList.add(indent + " String[] referralURLs = e.getReferralURLs();");
278 lineList.add(indent + " Control[] responseControls = " +
279 "e.getResponseControls();");
280 lineList.add(indent + '}');
281 }
282 }
283 }