001 /*
002 * Copyright 2007-2014 UnboundID Corp.
003 * All Rights Reserved.
004 */
005 /*
006 * Copyright (C) 2008-2014 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 com.unboundid.asn1.ASN1OctetString;
026 import com.unboundid.util.NotMutable;
027 import com.unboundid.util.ThreadSafety;
028 import com.unboundid.util.ThreadSafetyLevel;
029
030 import static com.unboundid.util.StaticUtils.*;
031 import static com.unboundid.util.Validator.*;
032
033
034
035 /**
036 * This class provides a SASL PLAIN bind request implementation as described in
037 * <A HREF="http://www.ietf.org/rfc/rfc4616.txt">RFC 4616</A>. The SASL PLAIN
038 * mechanism allows the client to authenticate with an authentication ID and
039 * password, and optionally allows the client to provide an authorization ID for
040 * use in performing subsequent operations.
041 * <BR><BR>
042 * Elements included in a PLAIN bind request include:
043 * <UL>
044 * <LI>Authentication ID -- A string which identifies the user that is
045 * attempting to authenticate. It should be an "authzId" value as
046 * described in section 5.2.1.8 of
047 * <A HREF="http://www.ietf.org/rfc/rfc4513.txt">RFC 4513</A>. That is,
048 * it should be either "dn:" followed by the distinguished name of the
049 * target user, or "u:" followed by the username. If the "u:" form is
050 * used, then the mechanism used to resolve the provided username to an
051 * entry may vary from server to server.</LI>
052 * <LI>Authorization ID -- An optional string which specifies an alternate
053 * authorization identity that should be used for subsequent operations
054 * requested on the connection. Like the authentication ID, the
055 * authorization ID should use the "authzId" syntax.</LI>
056 * <LI>Password -- The clear-text password for the target user.</LI>
057 * </UL>
058 * <H2>Example</H2>
059 * The following example demonstrates the process for performing a PLAIN bind
060 * against a directory server with a username of "test.user" and a password of
061 * "password":
062 * <PRE>
063 * PLAINBindRequest bindRequest =
064 * new PLAINBindRequest("u:test.user", "password");
065 * BindResult bindResult;
066 * try
067 * {
068 * bindResult = connection.bind(bindRequest);
069 * // If we get here, then the bind was successful.
070 * }
071 * catch (LDAPException le)
072 * {
073 * // The bind failed for some reason.
074 * bindResult = new BindResult(le.toLDAPResult());
075 * ResultCode resultCode = le.getResultCode();
076 * String errorMessageFromServer = le.getDiagnosticMessage();
077 * }
078 * </PRE>
079 */
080 @NotMutable()
081 @ThreadSafety(level=ThreadSafetyLevel.NOT_THREADSAFE)
082 public final class PLAINBindRequest
083 extends SASLBindRequest
084 {
085 /**
086 * The name for the PLAIN SASL mechanism.
087 */
088 public static final String PLAIN_MECHANISM_NAME = "PLAIN";
089
090
091
092 /**
093 * The serial version UID for this serializable class.
094 */
095 private static final long serialVersionUID = -5186140710317748684L;
096
097
098
099 // The password for this bind request.
100 private final ASN1OctetString password;
101
102 // The authentication ID string for this bind request.
103 private final String authenticationID;
104
105 // The authorization ID string for this bind request, if available.
106 private final String authorizationID;
107
108
109
110 /**
111 * Creates a new SASL PLAIN bind request with the provided authentication ID
112 * and password. It will not include an authorization ID or set of controls.
113 *
114 * @param authenticationID The authentication ID for this bind request. It
115 * must not be {@code null}.
116 * @param password The password for this bind request. It must not
117 * be {@code null}.
118 */
119 public PLAINBindRequest(final String authenticationID, final String password)
120 {
121 this(authenticationID, null, new ASN1OctetString(password), NO_CONTROLS);
122
123 ensureNotNull(password);
124 }
125
126
127
128 /**
129 * Creates a new SASL PLAIN bind request with the provided authentication ID
130 * and password. It will not include an authorization ID or set of controls.
131 *
132 * @param authenticationID The authentication ID for this bind request. It
133 * must not be {@code null}.
134 * @param password The password for this bind request. It must not
135 * be {@code null}.
136 */
137 public PLAINBindRequest(final String authenticationID, final byte[] password)
138 {
139 this(authenticationID, null, new ASN1OctetString(password), NO_CONTROLS);
140
141 ensureNotNull(password);
142 }
143
144
145
146 /**
147 * Creates a new SASL PLAIN bind request with the provided authentication ID
148 * and password. It will not include an authorization ID or set of controls.
149 *
150 * @param authenticationID The authentication ID for this bind request. It
151 * must not be {@code null}.
152 * @param password The password for this bind request. It must not
153 * be {@code null}.
154 */
155 public PLAINBindRequest(final String authenticationID,
156 final ASN1OctetString password)
157 {
158 this(authenticationID, null, password, NO_CONTROLS);
159 }
160
161
162
163 /**
164 * Creates a new SASL PLAIN bind request with the provided authentication ID,
165 * authorization ID, and password. It will not include a set of controls.
166 *
167 * @param authenticationID The authentication ID for this bind request. It
168 * must not be {@code null}.
169 * @param authorizationID The authorization ID for this bind request, or
170 * {@code null} if there is to be no authorization
171 * ID.
172 * @param password The password for this bind request. It must not
173 * be {@code null}.
174 */
175 public PLAINBindRequest(final String authenticationID,
176 final String authorizationID, final String password)
177 {
178 this(authenticationID, authorizationID, new ASN1OctetString(password),
179 NO_CONTROLS);
180
181 ensureNotNull(password);
182 }
183
184
185
186 /**
187 * Creates a new SASL PLAIN bind request with the provided authentication ID,
188 * authorization ID, and password. It will not include a set of controls.
189 *
190 * @param authenticationID The authentication ID for this bind request. It
191 * must not be {@code null}.
192 * @param authorizationID The authorization ID for this bind request, or
193 * {@code null} if there is to be no authorization
194 * ID.
195 * @param password The password for this bind request. It must not
196 * be {@code null}.
197 */
198 public PLAINBindRequest(final String authenticationID,
199 final String authorizationID, final byte[] password)
200 {
201 this(authenticationID, authorizationID, new ASN1OctetString(password),
202 NO_CONTROLS);
203
204 ensureNotNull(password);
205 }
206
207
208
209 /**
210 * Creates a new SASL PLAIN bind request with the provided authentication ID,
211 * authorization ID, and password. It will not include a set of controls.
212 *
213 * @param authenticationID The authentication ID for this bind request. It
214 * must not be {@code null}.
215 * @param authorizationID The authorization ID for this bind request, or
216 * {@code null} if there is to be no authorization
217 * ID.
218 * @param password The password for this bind request. It must not
219 * be {@code null}.
220 */
221 public PLAINBindRequest(final String authenticationID,
222 final String authorizationID,
223 final ASN1OctetString password)
224 {
225 this(authenticationID, authorizationID, password, NO_CONTROLS);
226 }
227
228
229
230 /**
231 * Creates a new SASL PLAIN bind request with the provided authentication ID,
232 * password, and set of controls. It will not include an authorization ID.
233 *
234 * @param authenticationID The authentication ID for this bind request. It
235 * must not be {@code null}.
236 * @param password The password for this bind request. It must not
237 * be {@code null}.
238 * @param controls The set of controls to include
239 */
240 public PLAINBindRequest(final String authenticationID, final String password,
241 final Control... controls)
242 {
243 this(authenticationID, null, new ASN1OctetString(password), controls);
244
245 ensureNotNull(password);
246 }
247
248
249
250 /**
251 * Creates a new SASL PLAIN bind request with the provided authentication ID,
252 * password, and set of controls. It will not include an authorization ID.
253 *
254 * @param authenticationID The authentication ID for this bind request. It
255 * must not be {@code null}.
256 * @param password The password for this bind request. It must not
257 * be {@code null}.
258 * @param controls The set of controls to include
259 */
260 public PLAINBindRequest(final String authenticationID, final byte[] password,
261 final Control... controls)
262 {
263 this(authenticationID, null, new ASN1OctetString(password), controls);
264
265 ensureNotNull(password);
266 }
267
268
269
270 /**
271 * Creates a new SASL PLAIN bind request with the provided authentication ID,
272 * password, and set of controls. It will not include an authorization ID.
273 *
274 * @param authenticationID The authentication ID for this bind request. It
275 * must not be {@code null}.
276 * @param password The password for this bind request. It must not
277 * be {@code null}.
278 * @param controls The set of controls to include
279 */
280 public PLAINBindRequest(final String authenticationID,
281 final ASN1OctetString password,
282 final Control... controls)
283 {
284 this(authenticationID, null, password, controls);
285 }
286
287
288
289 /**
290 * Creates a new SASL PLAIN bind request with the provided information.
291 *
292 * @param authenticationID The authentication ID for this bind request. It
293 * must not be {@code null}.
294 * @param authorizationID The authorization ID for this bind request, or
295 * {@code null} if there is to be no authorization
296 * ID.
297 * @param password The password for this bind request. It must not
298 * be {@code null}.
299 * @param controls The set of controls to include
300 */
301 public PLAINBindRequest(final String authenticationID,
302 final String authorizationID, final String password,
303 final Control... controls)
304 {
305 this(authenticationID, authorizationID, new ASN1OctetString(password),
306 controls);
307
308 ensureNotNull(password);
309 }
310
311
312
313 /**
314 * Creates a new SASL PLAIN bind request with the provided information.
315 *
316 * @param authenticationID The authentication ID for this bind request. It
317 * must not be {@code null}.
318 * @param authorizationID The authorization ID for this bind request, or
319 * {@code null} if there is to be no authorization
320 * ID.
321 * @param password The password for this bind request. It must not
322 * be {@code null}.
323 * @param controls The set of controls to include
324 */
325 public PLAINBindRequest(final String authenticationID,
326 final String authorizationID, final byte[] password,
327 final Control... controls)
328 {
329 this(authenticationID, authorizationID, new ASN1OctetString(password),
330 controls);
331
332 ensureNotNull(password);
333 }
334
335
336
337 /**
338 * Creates a new SASL PLAIN bind request with the provided information.
339 *
340 * @param authenticationID The authentication ID for this bind request. It
341 * must not be {@code null}.
342 * @param authorizationID The authorization ID for this bind request, or
343 * {@code null} if there is to be no authorization
344 * ID.
345 * @param password The password for this bind request. It must not
346 * be {@code null}.
347 * @param controls The set of controls to include
348 */
349 public PLAINBindRequest(final String authenticationID,
350 final String authorizationID,
351 final ASN1OctetString password,
352 final Control... controls)
353 {
354 super(controls);
355
356 ensureNotNull(authenticationID, password);
357
358 this.authenticationID = authenticationID;
359 this.authorizationID = authorizationID;
360 this.password = password;
361 }
362
363
364
365 /**
366 * {@inheritDoc}
367 */
368 @Override()
369 public String getSASLMechanismName()
370 {
371 return PLAIN_MECHANISM_NAME;
372 }
373
374
375
376 /**
377 * Retrieves the authentication ID for this bind request.
378 *
379 * @return The authentication ID for this bind request.
380 */
381 public String getAuthenticationID()
382 {
383 return authenticationID;
384 }
385
386
387
388 /**
389 * Retrieves the authorization ID for this bind request.
390 *
391 * @return The authorization ID for this bind request, or {@code null} if
392 * there is no authorization ID.
393 */
394 public String getAuthorizationID()
395 {
396 return authorizationID;
397 }
398
399
400
401 /**
402 * Retrieves the string representation of the password for this bind request.
403 *
404 * @return The string representation of the password for this bind request.
405 */
406 public String getPasswordString()
407 {
408 return password.stringValue();
409 }
410
411
412
413 /**
414 * Retrieves the bytes that comprise the the password for this bind request.
415 *
416 * @return The bytes that comprise the password for this bind request.
417 */
418 public byte[] getPasswordBytes()
419 {
420 return password.getValue();
421 }
422
423
424
425 /**
426 * Sends this bind request to the target server over the provided connection
427 * and returns the corresponding response.
428 *
429 * @param connection The connection to use to send this bind request to the
430 * server and read the associated response.
431 * @param depth The current referral depth for this request. It should
432 * always be one for the initial request, and should only
433 * be incremented when following referrals.
434 *
435 * @return The bind response read from the server.
436 *
437 * @throws LDAPException If a problem occurs while sending the request or
438 * reading the response.
439 */
440 @Override()
441 protected BindResult process(final LDAPConnection connection, final int depth)
442 throws LDAPException
443 {
444 // Create the byte array that should comprise the credentials.
445 final byte[] authZIDBytes = getBytes(authorizationID);
446 final byte[] authNIDBytes = getBytes(authenticationID);
447 final byte[] passwordBytes = password.getValue();
448 final byte[] credBytes = new byte[2 + authZIDBytes.length +
449 authNIDBytes.length + passwordBytes.length];
450
451 System.arraycopy(authZIDBytes, 0, credBytes, 0, authZIDBytes.length);
452
453 int pos = authZIDBytes.length + 1;
454 System.arraycopy(authNIDBytes, 0, credBytes, pos, authNIDBytes.length);
455
456 pos += authNIDBytes.length + 1;
457 System.arraycopy(passwordBytes, 0, credBytes, pos, passwordBytes.length);
458
459 return sendBindRequest(connection, "", new ASN1OctetString(credBytes),
460 getControls(), getResponseTimeoutMillis(connection));
461 }
462
463
464
465 /**
466 * {@inheritDoc}
467 */
468 @Override()
469 public PLAINBindRequest getRebindRequest(final String host, final int port)
470 {
471 return new PLAINBindRequest(authenticationID, authorizationID, password,
472 getControls());
473 }
474
475
476
477 /**
478 * {@inheritDoc}
479 */
480 @Override()
481 public PLAINBindRequest duplicate()
482 {
483 return duplicate(getControls());
484 }
485
486
487
488 /**
489 * {@inheritDoc}
490 */
491 @Override()
492 public PLAINBindRequest duplicate(final Control[] controls)
493 {
494 final PLAINBindRequest bindRequest = new PLAINBindRequest(authenticationID,
495 authorizationID, password, controls);
496 bindRequest.setResponseTimeoutMillis(getResponseTimeoutMillis(null));
497 return bindRequest;
498 }
499
500
501
502 /**
503 * {@inheritDoc}
504 */
505 @Override()
506 public void toString(final StringBuilder buffer)
507 {
508 buffer.append("PLAINBindRequest(authenticationID='");
509 buffer.append(authenticationID);
510 buffer.append('\'');
511
512 if (authorizationID != null)
513 {
514 buffer.append(", authorizationID='");
515 buffer.append(authorizationID);
516 buffer.append('\'');
517 }
518
519 final Control[] controls = getControls();
520 if (controls.length > 0)
521 {
522 buffer.append(", controls={");
523 for (int i=0; i < controls.length; i++)
524 {
525 if (i > 0)
526 {
527 buffer.append(", ");
528 }
529
530 buffer.append(controls[i]);
531 }
532 buffer.append('}');
533 }
534
535 buffer.append(')');
536 }
537 }