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.LdapCodecConstants; 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 codec The LDAP service instance 068 * @param decoratedMessage the decorated BindRequests. 069 */ 070 public BindRequestDecorator( LdapApiService codec, BindRequest decoratedMessage ) 071 { 072 super( codec, decoratedMessage ); 073 } 074 075 076 /** 077 * {@inheritDoc} 078 */ 079 @Override 080 public BindRequest setMessageId( int messageId ) 081 { 082 super.setMessageId( messageId ); 083 084 return this; 085 } 086 087 088 /** 089 * {@inheritDoc} 090 */ 091 @Override 092 public BindRequest addControl( Control control ) 093 { 094 return ( BindRequest ) super.addControl( control ); 095 } 096 097 098 /** 099 * {@inheritDoc} 100 */ 101 @Override 102 public BindRequest addAllControls( Control[] controls ) 103 { 104 return ( BindRequest ) super.addAllControls( controls ); 105 } 106 107 108 /** 109 * {@inheritDoc} 110 */ 111 @Override 112 public BindRequest removeControl( Control control ) 113 { 114 return ( BindRequest ) super.removeControl( control ); 115 } 116 117 118 //------------------------------------------------------------------------- 119 // The BindRequest methods 120 //------------------------------------------------------------------------- 121 122 /** 123 * {@inheritDoc} 124 */ 125 @Override 126 public boolean isSimple() 127 { 128 return getDecorated().isSimple(); 129 } 130 131 132 /** 133 * {@inheritDoc} 134 */ 135 @Override 136 public boolean getSimple() 137 { 138 return getDecorated().getSimple(); 139 } 140 141 142 /** 143 * {@inheritDoc} 144 */ 145 @Override 146 public BindRequest setSimple( boolean isSimple ) 147 { 148 getDecorated().setSimple( isSimple ); 149 150 return this; 151 } 152 153 154 /** 155 * {@inheritDoc} 156 */ 157 @Override 158 public byte[] getCredentials() 159 { 160 return getDecorated().getCredentials(); 161 } 162 163 164 /** 165 * {@inheritDoc} 166 */ 167 @Override 168 public BindRequest setCredentials( String credentials ) 169 { 170 getDecorated().setCredentials( credentials ); 171 172 return this; 173 } 174 175 176 /** 177 * {@inheritDoc} 178 */ 179 @Override 180 public BindRequest setCredentials( byte[] credentials ) 181 { 182 getDecorated().setCredentials( credentials ); 183 184 return this; 185 } 186 187 188 /** 189 * {@inheritDoc} 190 */ 191 @Override 192 public String getName() 193 { 194 return getDecorated().getName(); 195 } 196 197 198 /** 199 * {@inheritDoc} 200 */ 201 @Override 202 public BindRequest setName( String name ) 203 { 204 getDecorated().setName( name ); 205 206 return this; 207 } 208 209 210 /** 211 * {@inheritDoc} 212 */ 213 @Override 214 public Dn getDn() 215 { 216 return getDecorated().getDn(); 217 } 218 219 220 /** 221 * {@inheritDoc} 222 */ 223 @Override 224 public BindRequest setDn( Dn dn ) 225 { 226 getDecorated().setDn( dn ); 227 228 return this; 229 } 230 231 232 /** 233 * {@inheritDoc} 234 */ 235 @Override 236 public boolean isVersion3() 237 { 238 return getDecorated().isVersion3(); 239 } 240 241 242 /** 243 * {@inheritDoc} 244 */ 245 @Override 246 public boolean getVersion3() 247 { 248 return getDecorated().getVersion3(); 249 } 250 251 252 /** 253 * {@inheritDoc} 254 */ 255 @Override 256 public BindRequest setVersion3( boolean isVersion3 ) 257 { 258 getDecorated().setVersion3( isVersion3 ); 259 260 return this; 261 } 262 263 264 /** 265 * {@inheritDoc} 266 */ 267 @Override 268 public String getSaslMechanism() 269 { 270 return getDecorated().getSaslMechanism(); 271 } 272 273 274 /** 275 * {@inheritDoc} 276 */ 277 @Override 278 public BindRequest setSaslMechanism( String saslMechanism ) 279 { 280 getDecorated().setSaslMechanism( saslMechanism ); 281 282 return this; 283 } 284 285 286 //------------------------------------------------------------------------- 287 // The Decorator methods 288 //------------------------------------------------------------------------- 289 /** 290 * Compute the BindRequest length 291 * <br> 292 * BindRequest : 293 * <pre> 294 * 0x60 L1 295 * | 296 * +--> 0x02 0x01 (1..127) version 297 * +--> 0x04 L2 name 298 * +--> authentication 299 * 300 * L2 = Length(name) 301 * L3/4 = Length(authentication) 302 * Length(BindRequest) = Length(0x60) + Length(L1) + L1 + Length(0x02) + 1 + 1 + 303 * Length(0x04) + Length(L2) + L2 + Length(authentication) 304 * </pre> 305 */ 306 @Override 307 public int computeLength() 308 { 309 // Initialized with version 310 bindRequestLength = 1 + 1 + 1; 311 312 Dn dn = getDn(); 313 314 if ( !Dn.isNullOrEmpty( dn ) ) 315 { 316 // A DN has been provided 317 dnBytes = Strings.getBytesUtf8( dn.getName() ); 318 int dnLength = dnBytes.length; 319 320 bindRequestLength += 1 + TLV.getNbBytes( dnLength ) + dnLength; 321 } 322 else 323 { 324 // No DN has been provided, let's use the name as a string instead 325 String name = getName(); 326 327 if ( Strings.isEmpty( name ) ) 328 { 329 name = ""; 330 } 331 332 nameBytes = Strings.getBytesUtf8( name ); 333 334 bindRequestLength += 1 + TLV.getNbBytes( nameBytes.length ) + nameBytes.length; 335 } 336 337 byte[] credentials = getCredentials(); 338 339 // The authentication 340 if ( isSimple() ) 341 { 342 // Compute a SimpleBind operation 343 if ( credentials != null ) 344 { 345 bindRequestLength += 1 + TLV.getNbBytes( credentials.length ) + credentials.length; 346 } 347 else 348 { 349 bindRequestLength += 1 + 1; 350 } 351 } 352 else 353 { 354 mechanismBytes = Strings.getBytesUtf8( getSaslMechanism() ); 355 saslMechanismLength = 1 + TLV.getNbBytes( mechanismBytes.length ) + mechanismBytes.length; 356 357 if ( credentials != null ) 358 { 359 saslCredentialsLength = 1 + TLV.getNbBytes( credentials.length ) + credentials.length; 360 } 361 362 int saslLength = 1 + TLV.getNbBytes( saslMechanismLength + saslCredentialsLength ) + saslMechanismLength 363 + saslCredentialsLength; 364 365 bindRequestLength += saslLength; 366 } 367 368 // Return the result. 369 return 1 + TLV.getNbBytes( bindRequestLength ) + bindRequestLength; 370 } 371 372 373 /** 374 * Encode the BindRequest message to a PDU. 375 * <br> 376 * BindRequest : 377 * <pre> 378 * 0x60 LL 379 * 0x02 LL version 0x80 LL simple 380 * 0x04 LL name / 381 * authentication.encode() 382 * \ 0x83 LL mechanism [0x04 LL credential] 383 * </pre> 384 * 385 * @param buffer The buffer where to put the PDU 386 * @return The PDU. 387 */ 388 @Override 389 public ByteBuffer encode( ByteBuffer buffer ) throws EncoderException 390 { 391 try 392 { 393 // The BindRequest Tag 394 buffer.put( LdapCodecConstants.BIND_REQUEST_TAG ); 395 buffer.put( TLV.getBytes( bindRequestLength ) ); 396 397 } 398 catch ( BufferOverflowException boe ) 399 { 400 throw new EncoderException( I18n.err( I18n.ERR_04005 ), boe ); 401 } 402 403 // The version (LDAP V3 only) 404 BerValue.encode( buffer, 3 ); 405 406 Dn dn = getDn(); 407 408 if ( !Dn.isNullOrEmpty( dn ) ) 409 { 410 // A DN has been provided 411 BerValue.encode( buffer, dnBytes ); 412 } 413 else 414 { 415 // No DN has been provided, let's use the name as a string instead 416 BerValue.encode( buffer, nameBytes ); 417 } 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 ) LdapCodecConstants.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, boe ); 448 } 449 } 450 else 451 { 452 // SASL Bind 453 try 454 { 455 // The saslAuthentication Tag 456 buffer.put( ( byte ) LdapCodecConstants.BIND_REQUEST_SASL_TAG ); 457 458 buffer.put( TLV 459 .getBytes( saslMechanismLength + saslCredentialsLength ) ); 460 461 BerValue.encode( buffer, mechanismBytes ); 462 463 if ( credentials != null ) 464 { 465 BerValue.encode( buffer, credentials ); 466 } 467 } 468 catch ( BufferOverflowException boe ) 469 { 470 String msg = I18n.err( I18n.ERR_04005 ); 471 throw new EncoderException( msg, boe ); 472 } 473 } 474 475 return buffer; 476 } 477}