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