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