001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * https://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 * 019 */ 020package org.apache.directory.api.ldap.model.message; 021 022 023import java.util.Arrays; 024 025import org.apache.directory.api.i18n.I18n; 026import org.apache.directory.api.ldap.model.name.Dn; 027import org.apache.directory.api.util.Strings; 028 029 030/** 031 * Bind protocol operation request which authenticates and begins a client 032 * session. Does not yet contain interfaces for SASL authentication mechanisms. 033 * 034 * @author <a href="mailto:dev@directory.apache.org"> Apache Directory Project</a> 035 */ 036public class BindRequestImpl extends AbstractAbandonableRequest implements BindRequest 037{ 038 /** 039 * Distinguished name identifying the name of the authenticating subject - 040 * defaults to the empty string 041 */ 042 private Dn dn; 043 044 /** 045 * String identifying the name of the authenticating subject - 046 * defaults to the empty string 047 */ 048 private String name; 049 050 /** The passwords, keys or tickets used to verify user identity */ 051 private byte[] credentials; 052 053 /** A storage for credentials hashCode */ 054 private int hCredentials; 055 056 /** The mechanism used to decode user identity */ 057 private String mechanism; 058 059 /** Simple vs. SASL authentication mode flag */ 060 private boolean isSimple = true; 061 062 /** Bind behavior exhibited by protocol version */ 063 private boolean isVersion3 = true; 064 065 /** The associated response */ 066 private BindResponse response; 067 068 069 // ------------------------------------------------------------------------ 070 // Constructors 071 // ------------------------------------------------------------------------ 072 /** 073 * Creates an BindRequest implementation to bind to an LDAP server. 074 */ 075 public BindRequestImpl() 076 { 077 super( -1, MessageTypeEnum.BIND_REQUEST ); 078 hCredentials = 0; 079 } 080 081 082 // ----------------------------------------------------------------------- 083 // BindRequest Interface Method Implementations 084 // ----------------------------------------------------------------------- 085 086 /** 087 * {@inheritDoc} 088 */ 089 @Override 090 public boolean isSimple() 091 { 092 return isSimple; 093 } 094 095 096 /** 097 * {@inheritDoc} 098 */ 099 @Override 100 public boolean getSimple() 101 { 102 return isSimple; 103 } 104 105 106 /** 107 * {@inheritDoc} 108 */ 109 @Override 110 public BindRequest setSimple( boolean simple ) 111 { 112 this.isSimple = simple; 113 114 return this; 115 } 116 117 118 /** 119 * {@inheritDoc} 120 */ 121 @Override 122 public byte[] getCredentials() 123 { 124 return credentials; 125 } 126 127 128 /** 129 * {@inheritDoc} 130 */ 131 @Override 132 public BindRequest setCredentials( String credentials ) 133 { 134 return setCredentials( Strings.getBytesUtf8( credentials ) ); 135 } 136 137 138 /** 139 * {@inheritDoc} 140 */ 141 @Override 142 public BindRequest setCredentials( byte[] credentials ) 143 { 144 if ( credentials != null ) 145 { 146 this.credentials = new byte[credentials.length]; 147 System.arraycopy( credentials, 0, this.credentials, 0, credentials.length ); 148 } 149 else 150 { 151 this.credentials = null; 152 } 153 154 // Compute the hashcode 155 if ( credentials != null ) 156 { 157 hCredentials = 0; 158 159 for ( byte b : credentials ) 160 { 161 hCredentials = hCredentials * 31 + b; 162 } 163 } 164 else 165 { 166 hCredentials = 0; 167 } 168 169 return this; 170 } 171 172 173 /** 174 * {@inheritDoc} 175 */ 176 @Override 177 public String getSaslMechanism() 178 { 179 return mechanism; 180 } 181 182 183 /** 184 * {@inheritDoc} 185 */ 186 @Override 187 public BindRequest setSaslMechanism( String saslMechanism ) 188 { 189 this.isSimple = false; 190 this.mechanism = saslMechanism; 191 192 return this; 193 } 194 195 196 /** 197 * {@inheritDoc} 198 */ 199 @Override 200 public String getName() 201 { 202 return name; 203 } 204 205 206 /** 207 * {@inheritDoc} 208 */ 209 @Override 210public BindRequest setName( String name ) 211 { 212 this.name = name; 213 214 return this; 215 } 216 217 218 /** 219 * {@inheritDoc} 220 */ 221 @Override 222 public Dn getDn() 223 { 224 return dn; 225 } 226 227 228 /** 229 * {@inheritDoc} 230 */ 231 @Override 232 public BindRequest setDn( Dn dn ) 233 { 234 this.dn = dn; 235 this.name = dn.getName(); 236 237 return this; 238 } 239 240 241 /** 242 * {@inheritDoc} 243 */ 244 @Override 245 public boolean isVersion3() 246 { 247 return isVersion3; 248 } 249 250 251 /** 252 * {@inheritDoc} 253 */ 254 @Override 255 public boolean getVersion3() 256 { 257 return isVersion3; 258 } 259 260 261 /** 262 * {@inheritDoc} 263 */ 264 @Override 265 public BindRequest setVersion3( boolean version3 ) 266 { 267 this.isVersion3 = version3; 268 269 return this; 270 } 271 272 273 /** 274 * {@inheritDoc} 275 */ 276 @Override 277 public BindRequest setMessageId( int messageId ) 278 { 279 super.setMessageId( messageId ); 280 281 return this; 282 } 283 284 285 /** 286 * {@inheritDoc} 287 */ 288 @Override 289 public BindRequest addControl( Control control ) 290 { 291 return ( BindRequest ) super.addControl( control ); 292 } 293 294 295 /** 296 * {@inheritDoc} 297 */ 298 @Override 299 public BindRequest addAllControls( Control[] controls ) 300 { 301 return ( BindRequest ) super.addAllControls( controls ); 302 } 303 304 305 /** 306 * {@inheritDoc} 307 */ 308 @Override 309 public BindRequest removeControl( Control control ) 310 { 311 return ( BindRequest ) super.removeControl( control ); 312 } 313 314 315 // ----------------------------------------------------------------------- 316 // BindRequest Interface Method Implementations 317 // ----------------------------------------------------------------------- 318 /** 319 * Gets the protocol response message type for this request which produces 320 * at least one response. 321 * 322 * @return the message type of the response. 323 */ 324 @Override 325 public MessageTypeEnum getResponseType() 326 { 327 return MessageTypeEnum.BIND_RESPONSE; 328 } 329 330 331 /** 332 * The result containing response for this request. 333 * 334 * @return the result containing response for this request 335 */ 336 @Override 337 public BindResponse getResultResponse() 338 { 339 if ( response == null ) 340 { 341 response = new BindResponseImpl( getMessageId() ); 342 } 343 344 return response; 345 } 346 347 348 /** 349 * RFC 2251/4511 [Section 4.11]: Abandon, Bind, Unbind, and StartTLS operations 350 * cannot be abandoned. 351 */ 352 @Override 353 public void abandon() 354 { 355 throw new UnsupportedOperationException( I18n.err( I18n.ERR_13506_CANNOT_ABANDON_OPERATION ) ); 356 } 357 358 359 /** 360 * {@inheritDoc} 361 */ 362 @Override 363 public boolean equals( Object obj ) 364 { 365 if ( obj == this ) 366 { 367 return true; 368 } 369 370 if ( !( obj instanceof BindRequest ) ) 371 { 372 return false; 373 } 374 375 if ( !super.equals( obj ) ) 376 { 377 return false; 378 } 379 380 BindRequest req = ( BindRequest ) obj; 381 382 if ( req.isSimple() != isSimple() ) 383 { 384 return false; 385 } 386 387 if ( req.isVersion3() != isVersion3() ) 388 { 389 return false; 390 } 391 392 String name1 = req.getName(); 393 String name2 = getName(); 394 395 if ( Strings.isEmpty( name1 ) ) 396 { 397 if ( !Strings.isEmpty( name2 ) ) 398 { 399 return false; 400 } 401 } 402 else 403 { 404 if ( Strings.isEmpty( name2 ) ) 405 { 406 return false; 407 } 408 else if ( !name2.equals( name1 ) ) 409 { 410 return false; 411 } 412 } 413 414 Dn dn1 = req.getDn(); 415 Dn dn2 = getDn(); 416 417 if ( Dn.isNullOrEmpty( dn1 ) ) 418 { 419 if ( !Dn.isNullOrEmpty( dn2 ) ) 420 { 421 return false; 422 } 423 } 424 else 425 { 426 if ( Dn.isNullOrEmpty( dn2 ) ) 427 { 428 return false; 429 } 430 else if ( !dn1.equals( dn2 ) ) 431 { 432 return false; 433 } 434 } 435 436 return Arrays.equals( req.getCredentials(), getCredentials() ); 437 } 438 439 440 /** 441 * {@inheritDoc} 442 */ 443 @Override 444 public int hashCode() 445 { 446 int hash = 37; 447 hash = hash * 17 + ( credentials == null ? 0 : hCredentials ); 448 hash = hash * 17 + ( isSimple ? 0 : 1 ); 449 hash = hash * 17 + ( isVersion3 ? 0 : 1 ); 450 hash = hash * 17 + ( mechanism == null ? 0 : mechanism.hashCode() ); 451 hash = hash * 17 + ( name == null ? 0 : name.hashCode() ); 452 hash = hash * 17 + ( response == null ? 0 : response.hashCode() ); 453 hash = hash * 17 + super.hashCode(); 454 455 return hash; 456 } 457 458 459 /** 460 * Get a String representation of a BindRequest 461 * 462 * @return A BindRequest String 463 */ 464 @Override 465 public String toString() 466 { 467 StringBuilder sb = new StringBuilder(); 468 469 sb.append( " BindRequest\n" ); 470 sb.append( " Version : '" ).append( isVersion3 ? "3" : "2" ).append( "'\n" ); 471 472 if ( isSimple ) 473 { 474 if ( ( Strings.isEmpty( name ) && ( ( dn == null ) || dn.equals( Dn.EMPTY_DN ) ) ) ) 475 { 476 sb.append( " Name : anonymous\n" ); 477 } 478 else 479 { 480 sb.append( " Name : '" ).append( name ).append( "'\n" ); 481 sb.append( " Simple authentication : '" ).append( "(omitted-for-safety)" ).append( "'\n" ); 482 } 483 } 484 else 485 { 486 sb.append( " Sasl credentials\n" ); 487 sb.append( " Mechanism :'" ).append( mechanism ).append( "'\n" ); 488 489 if ( credentials == null ) 490 { 491 sb.append( " Credentials : null" ); 492 } 493 else 494 { 495 sb.append( " Credentials : (omitted-for-safety)" ); 496 } 497 } 498 499 // The controls if any 500 return super.toString( sb.toString() ); 501 } 502}