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