View Javadoc
1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one
3    *  or more contributor license agreements.  See the NOTICE file
4    *  distributed with this work for additional information
5    *  regarding copyright ownership.  The ASF licenses this file
6    *  to you under the Apache License, Version 2.0 (the
7    *  "License"); you may not use this file except in compliance
8    *  with the License.  You may obtain a copy of the License at
9    * 
10   *    http://www.apache.org/licenses/LICENSE-2.0
11   * 
12   *  Unless required by applicable law or agreed to in writing,
13   *  software distributed under the License is distributed on an
14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *  KIND, either express or implied.  See the License for the
16   *  specific language governing permissions and limitations
17   *  under the License.
18   * 
19   */
20  package org.apache.directory.api.ldap.codec.decorators;
21  
22  
23  import java.nio.BufferOverflowException;
24  import java.nio.ByteBuffer;
25  
26  import org.apache.directory.api.asn1.EncoderException;
27  import org.apache.directory.api.asn1.ber.tlv.BerValue;
28  import org.apache.directory.api.asn1.ber.tlv.TLV;
29  import org.apache.directory.api.i18n.I18n;
30  import org.apache.directory.api.ldap.codec.api.LdapApiService;
31  import org.apache.directory.api.ldap.codec.api.LdapConstants;
32  import org.apache.directory.api.ldap.model.message.BindRequest;
33  import org.apache.directory.api.ldap.model.message.Control;
34  import org.apache.directory.api.ldap.model.name.Dn;
35  import org.apache.directory.api.util.Strings;
36  
37  
38  /**
39   * A decorator for the BindRequest message
40   *
41   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
42   */
43  public class BindRequestDecorator extends SingleReplyRequestDecorator<BindRequest> implements BindRequest
44  {
45      /** The bind request length */
46      private int bindRequestLength;
47  
48      /** The SASL Mechanism length */
49      private int saslMechanismLength;
50  
51      /** The SASL credentials length */
52      private int saslCredentialsLength;
53  
54      /** The bytes containing the Dn */
55      private byte[] dnBytes;
56  
57      /** The bytes containing the Name */
58      private byte[] nameBytes;
59  
60      /** The bytes containing the SaslMechanism */
61      private byte[] mechanismBytes;
62  
63  
64      /**
65       * Makes a BindRequest a MessageDecorator.
66       *
67       * @param decoratedMessage the decorated BindRequests.
68       */
69      public BindRequestDecorator( LdapApiService codec, BindRequest decoratedMessage )
70      {
71          super( codec, decoratedMessage );
72      }
73  
74  
75      /**
76       * Stores the encoded length for the BindRequest
77       * @param bindRequestLength The encoded length
78       */
79      public void setBindRequestLength( int bindRequestLength )
80      {
81          this.bindRequestLength = bindRequestLength;
82      }
83  
84  
85      /**
86       * @return The encoded BindRequest's length
87       */
88      public int getBindRequestLength()
89      {
90          return bindRequestLength;
91      }
92  
93  
94      /**
95       * Stores the encoded length for the SaslCredentials
96       * @param saslCredentialsLength The encoded length
97       */
98      public void setSaslCredentialsLength( int saslCredentialsLength )
99      {
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 }