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.LdapCodecConstants;
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 codec The LDAP service instance
68       * @param decoratedMessage the decorated BindRequests.
69       */
70      public BindRequestDecorator( LdapApiService codec, BindRequest decoratedMessage )
71      {
72          super( codec, decoratedMessage );
73      }
74  
75  
76      /**
77       * {@inheritDoc}
78       */
79      @Override
80      public BindRequest setMessageId( int messageId )
81      {
82          super.setMessageId( messageId );
83  
84          return this;
85      }
86  
87  
88      /**
89       * {@inheritDoc}
90       */
91      @Override
92      public BindRequest addControl( Control control )
93      {
94          return ( BindRequest ) super.addControl( control );
95      }
96  
97  
98      /**
99       * {@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      *   +--&gt; 0x02 0x01 (1..127) version
297      *   +--&gt; 0x04 L2 name
298      *   +--&gt; 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 }