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