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.codec.decorators; 021 022 023import java.nio.BufferOverflowException; 024import java.nio.ByteBuffer; 025 026import org.apache.directory.shared.asn1.EncoderException; 027import org.apache.directory.shared.asn1.ber.tlv.TLV; 028import org.apache.directory.shared.asn1.ber.tlv.Value; 029import org.apache.directory.shared.i18n.I18n; 030import org.apache.directory.shared.ldap.codec.api.LdapApiService; 031import org.apache.directory.shared.ldap.codec.api.LdapConstants; 032import org.apache.directory.shared.ldap.model.exception.MessageException; 033import org.apache.directory.shared.ldap.model.message.BindRequest; 034import org.apache.directory.shared.ldap.model.message.BindResponse; 035import org.apache.directory.shared.ldap.model.message.Control; 036import org.apache.directory.shared.ldap.model.name.Dn; 037import org.apache.directory.shared.util.Strings; 038 039 040/** 041 * A decorator for the BindRequest message 042 * 043 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 044 */ 045public class BindRequestDecorator extends SingleReplyRequestDecorator<BindRequest,BindResponse> 046 implements BindRequest 047{ 048 /** The bind request length */ 049 private int bindRequestLength; 050 051 /** The SASL Mechanism length */ 052 private int saslMechanismLength; 053 054 /** The SASL credentials length */ 055 private int saslCredentialsLength; 056 057 058 /** 059 * Makes a BindRequest a MessageDecorator. 060 * 061 * @param decoratedMessage the decorated BindRequests. 062 */ 063 public BindRequestDecorator( LdapApiService codec, BindRequest decoratedMessage ) 064 { 065 super( codec, decoratedMessage ); 066 } 067 068 069 /** 070 * Stores the encoded length for the BindRequest 071 * @param bindRequestLength The encoded length 072 */ 073 public void setBindRequestLength( int bindRequestLength ) 074 { 075 this.bindRequestLength = bindRequestLength; 076 } 077 078 079 /** 080 * @return The encoded BindRequest's length 081 */ 082 public int getBindRequestLength() 083 { 084 return bindRequestLength; 085 } 086 087 088 /** 089 * Stores the encoded length for the SaslCredentials 090 * @param saslCredentialsLength The encoded length 091 */ 092 public void setSaslCredentialsLength( int saslCredentialsLength ) 093 { 094 this.saslCredentialsLength = saslCredentialsLength; 095 } 096 097 098 /** 099 * @return The encoded SaslCredentials's length 100 */ 101 public int getSaslCredentialsLength() 102 { 103 return saslCredentialsLength; 104 } 105 106 107 /** 108 * Stores the encoded length for the Mechanism 109 * @param saslMechanismLength The encoded length 110 */ 111 public void setSaslMechanismLength( int saslMechanismLength ) 112 { 113 this.saslMechanismLength = saslMechanismLength; 114 } 115 116 117 /** 118 * @return The encoded SaslMechanism's length 119 */ 120 public int getSaslMechanismLength() 121 { 122 return saslMechanismLength; 123 } 124 125 126 /** 127 * {@inheritDoc} 128 */ 129 public BindRequest setMessageId( int messageId ) 130 { 131 super.setMessageId( messageId ); 132 133 return this; 134 } 135 136 137 /** 138 * {@inheritDoc} 139 */ 140 public BindRequest addControl( Control control ) throws MessageException 141 { 142 return (BindRequest)super.addControl( control ); 143 } 144 145 146 /** 147 * {@inheritDoc} 148 */ 149 public BindRequest addAllControls( Control[] controls ) throws MessageException 150 { 151 return (BindRequest)super.addAllControls( controls ); 152 } 153 154 155 /** 156 * {@inheritDoc} 157 */ 158 public BindRequest removeControl( Control control ) throws MessageException 159 { 160 return (BindRequest)super.removeControl( control ); 161 } 162 163 164 //------------------------------------------------------------------------- 165 // The BindRequest methods 166 //------------------------------------------------------------------------- 167 168 169 /** 170 * {@inheritDoc} 171 */ 172 public boolean isSimple() 173 { 174 return getDecorated().isSimple(); 175 } 176 177 178 /** 179 * {@inheritDoc} 180 */ 181 public boolean getSimple() 182 { 183 return getDecorated().getSimple(); 184 } 185 186 187 /** 188 * {@inheritDoc} 189 */ 190 public BindRequest setSimple( boolean isSimple ) 191 { 192 getDecorated().setSimple( isSimple ); 193 194 return this; 195 } 196 197 198 /** 199 * {@inheritDoc} 200 */ 201 public byte[] getCredentials() 202 { 203 return getDecorated().getCredentials(); 204 } 205 206 207 /** 208 * {@inheritDoc} 209 */ 210 public BindRequest setCredentials( String credentials ) 211 { 212 getDecorated().setCredentials( credentials ); 213 214 return this; 215 } 216 217 218 /** 219 * {@inheritDoc} 220 */ 221 public BindRequest setCredentials( byte[] credentials ) 222 { 223 getDecorated().setCredentials( credentials ); 224 225 return this; 226 } 227 228 229 /** 230 * {@inheritDoc} 231 */ 232 public Dn getName() 233 { 234 return getDecorated().getName(); 235 } 236 237 238 /** 239 * {@inheritDoc} 240 */ 241 public BindRequest setName( Dn name ) 242 { 243 getDecorated().setName( name ); 244 245 return this; 246 } 247 248 249 /** 250 * {@inheritDoc} 251 */ 252 public boolean isVersion3() 253 { 254 return getDecorated().isVersion3(); 255 } 256 257 258 /** 259 * {@inheritDoc} 260 */ 261 public boolean getVersion3() 262 { 263 return getDecorated().getVersion3(); 264 } 265 266 267 /** 268 * {@inheritDoc} 269 */ 270 public BindRequest setVersion3( boolean isVersion3 ) 271 { 272 getDecorated().setVersion3( isVersion3 ); 273 274 return this; 275 } 276 277 278 /** 279 * {@inheritDoc} 280 */ 281 public String getSaslMechanism() 282 { 283 return getDecorated().getSaslMechanism(); 284 } 285 286 287 /** 288 * {@inheritDoc} 289 */ 290 public BindRequest setSaslMechanism( String saslMechanism ) 291 { 292 getDecorated().setSaslMechanism( saslMechanism ); 293 294 return this; 295 } 296 297 298 //------------------------------------------------------------------------- 299 // The Decorator methods 300 //------------------------------------------------------------------------- 301 /** 302 * Compute the BindRequest length 303 * 304 * BindRequest : 305 * <pre> 306 * 0x60 L1 307 * | 308 * +--> 0x02 0x01 (1..127) version 309 * +--> 0x04 L2 name 310 * +--> authentication 311 * 312 * L2 = Length(name) 313 * L3/4 = Length(authentication) 314 * Length(BindRequest) = Length(0x60) + Length(L1) + L1 + Length(0x02) + 1 + 1 + 315 * Length(0x04) + Length(L2) + L2 + Length(authentication) 316 * </pre> 317 */ 318 public int computeLength() 319 { 320 int bindRequestLength = 1 + 1 + 1; // Initialized with version 321 322 Dn name = getName(); 323 324 // The name 325 if ( name == null ) 326 { 327 name = Dn.EMPTY_DN; 328 } 329 330 bindRequestLength += 1 + TLV.getNbBytes( Dn.getNbBytes( name ) ) 331 + Dn.getNbBytes( name ); 332 333 byte[] credentials = getCredentials(); 334 335 // The authentication 336 if ( isSimple() ) 337 { 338 // Compute a SimpleBind operation 339 if ( credentials != null ) 340 { 341 bindRequestLength += 1 + TLV.getNbBytes( credentials.length ) + credentials.length; 342 } 343 else 344 { 345 bindRequestLength += 1 + 1; 346 } 347 } 348 else 349 { 350 byte[] mechanismBytes = Strings.getBytesUtf8( getSaslMechanism() ); 351 int saslMechanismLength = 1 + TLV.getNbBytes( mechanismBytes.length ) + mechanismBytes.length; 352 int saslCredentialsLength = 0; 353 354 if ( credentials != null ) 355 { 356 saslCredentialsLength = 1 + TLV.getNbBytes( credentials.length ) + credentials.length; 357 } 358 359 int saslLength = 1 + TLV.getNbBytes( saslMechanismLength + saslCredentialsLength ) + saslMechanismLength 360 + saslCredentialsLength; 361 362 bindRequestLength += saslLength; 363 364 // Store the mechanism and credentials lengths 365 setSaslMechanismLength( saslMechanismLength ); 366 setSaslCredentialsLength( saslCredentialsLength ); 367 } 368 369 setBindRequestLength( bindRequestLength ); 370 371 // Return the result. 372 return 1 + TLV.getNbBytes( bindRequestLength ) + bindRequestLength; 373 } 374 375 376 /** 377 * Encode the BindRequest message to a PDU. 378 * 379 * BindRequest : 380 * <pre> 381 * 0x60 LL 382 * 0x02 LL version 0x80 LL simple 383 * 0x04 LL name / 384 * authentication.encode() 385 * \ 0x83 LL mechanism [0x04 LL credential] 386 * </pre> 387 * 388 * @param buffer The buffer where to put the PDU 389 * @return The PDU. 390 */ 391 public ByteBuffer encode( ByteBuffer buffer ) throws EncoderException 392 { 393 try 394 { 395 // The BindRequest Tag 396 buffer.put( LdapConstants.BIND_REQUEST_TAG ); 397 buffer.put( TLV.getBytes( getBindRequestLength() ) ); 398 399 } 400 catch ( BufferOverflowException boe ) 401 { 402 throw new EncoderException( I18n.err( I18n.ERR_04005 ) ); 403 } 404 405 // The version (LDAP V3 only) 406 Value.encode( buffer, 3 ); 407 408 // The name 409 Dn name = getName(); 410 411 // The name 412 if ( name == null ) 413 { 414 name = Dn.EMPTY_DN; 415 } 416 417 Value.encode( buffer, Dn.getBytes( name ) ); 418 419 byte[] credentials = getCredentials(); 420 421 // The authentication 422 if ( isSimple() ) 423 { 424 // Simple authentication 425 try 426 { 427 // The simpleAuthentication Tag 428 buffer.put( ( byte ) LdapConstants.BIND_REQUEST_SIMPLE_TAG ); 429 430 if ( credentials != null ) 431 { 432 buffer.put( TLV.getBytes( credentials.length ) ); 433 434 if ( credentials.length != 0 ) 435 { 436 buffer.put( credentials ); 437 } 438 } 439 else 440 { 441 buffer.put( ( byte ) 0 ); 442 } 443 } 444 catch ( BufferOverflowException boe ) 445 { 446 String msg = I18n.err( I18n.ERR_04005 ); 447 throw new EncoderException( msg ); 448 } 449 } 450 else 451 { 452 // SASL Bind 453 try 454 { 455 // The saslAuthentication Tag 456 buffer.put( ( byte ) LdapConstants.BIND_REQUEST_SASL_TAG ); 457 458 byte[] mechanismBytes = Strings.getBytesUtf8( getSaslMechanism() ); 459 460 buffer.put( TLV 461 .getBytes( getSaslMechanismLength() + getSaslCredentialsLength() ) ); 462 463 Value.encode( buffer, mechanismBytes ); 464 465 if ( credentials != null ) 466 { 467 Value.encode( buffer, credentials ); 468 } 469 } 470 catch ( BufferOverflowException boe ) 471 { 472 String msg = I18n.err( I18n.ERR_04005 ); 473 throw new EncoderException( msg ); 474 } 475 } 476 477 return buffer; 478 } 479}