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