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 */ 021package com.unboundid.ldap.sdk; 022 023 024 025import com.unboundid.asn1.ASN1OctetString; 026import com.unboundid.util.NotMutable; 027import com.unboundid.util.ThreadSafety; 028import com.unboundid.util.ThreadSafetyLevel; 029 030import static com.unboundid.util.StaticUtils.*; 031import 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) 082public 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}