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   *    https://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.model.message;
21  
22  
23  import java.util.Arrays;
24  
25  import org.apache.directory.api.i18n.I18n;
26  import org.apache.directory.api.ldap.model.name.Dn;
27  import org.apache.directory.api.util.Strings;
28  
29  
30  /**
31   * Bind protocol operation request which authenticates and begins a client
32   * session. Does not yet contain interfaces for SASL authentication mechanisms.
33   *
34   * @author <a href="mailto:dev@directory.apache.org"> Apache Directory Project</a>
35   */
36  public class BindRequestImpl extends AbstractAbandonableRequest implements BindRequest
37  {
38      /**
39       * Distinguished name identifying the name of the authenticating subject -
40       * defaults to the empty string
41       */
42      private Dn dn;
43  
44      /**
45       * String identifying the name of the authenticating subject -
46       * defaults to the empty string
47       */
48      private String name;
49  
50      /** The passwords, keys or tickets used to verify user identity */
51      private byte[] credentials;
52  
53      /** A storage for credentials hashCode */
54      private int hCredentials;
55  
56      /** The mechanism used to decode user identity */
57      private String mechanism;
58  
59      /** Simple vs. SASL authentication mode flag */
60      private boolean isSimple = true;
61  
62      /** Bind behavior exhibited by protocol version */
63      private boolean isVersion3 = true;
64  
65      /** The associated response */
66      private BindResponse response;
67  
68  
69      // ------------------------------------------------------------------------
70      // Constructors
71      // ------------------------------------------------------------------------
72      /**
73       * Creates an BindRequest implementation to bind to an LDAP server.
74       */
75      public BindRequestImpl()
76      {
77          super( -1, MessageTypeEnum.BIND_REQUEST );
78          hCredentials = 0;
79      }
80  
81  
82      // -----------------------------------------------------------------------
83      // BindRequest Interface Method Implementations
84      // -----------------------------------------------------------------------
85  
86      /**
87       * {@inheritDoc}
88       */
89      @Override
90      public boolean isSimple()
91      {
92          return isSimple;
93      }
94  
95  
96      /**
97       * {@inheritDoc}
98       */
99      @Override
100     public boolean getSimple()
101     {
102         return isSimple;
103     }
104 
105 
106     /**
107      * {@inheritDoc}
108      */
109     @Override
110     public BindRequest setSimple( boolean simple )
111     {
112         this.isSimple = simple;
113 
114         return this;
115     }
116 
117 
118     /**
119      * {@inheritDoc}
120      */
121     @Override
122     public byte[] getCredentials()
123     {
124         return credentials;
125     }
126 
127 
128     /**
129      * {@inheritDoc}
130      */
131     @Override
132     public BindRequest setCredentials( String credentials )
133     {
134         return setCredentials( Strings.getBytesUtf8( credentials ) );
135     }
136 
137 
138     /**
139      * {@inheritDoc}
140      */
141     @Override
142     public BindRequest setCredentials( byte[] credentials )
143     {
144         if ( credentials != null )
145         {
146             this.credentials = new byte[credentials.length];
147             System.arraycopy( credentials, 0, this.credentials, 0, credentials.length );
148         }
149         else
150         {
151             this.credentials = null;
152         }
153 
154         // Compute the hashcode
155         if ( credentials != null )
156         {
157             hCredentials = 0;
158 
159             for ( byte b : credentials )
160             {
161                 hCredentials = hCredentials * 31 + b;
162             }
163         }
164         else
165         {
166             hCredentials = 0;
167         }
168 
169         return this;
170     }
171 
172 
173     /**
174      * {@inheritDoc}
175      */
176     @Override
177     public String getSaslMechanism()
178     {
179         return mechanism;
180     }
181 
182 
183     /**
184      * {@inheritDoc}
185      */
186     @Override
187     public BindRequest setSaslMechanism( String saslMechanism )
188     {
189         this.isSimple = false;
190         this.mechanism = saslMechanism;
191 
192         return this;
193     }
194 
195 
196     /**
197      * {@inheritDoc}
198      */
199     @Override
200     public String getName()
201     {
202         return name;
203     }
204 
205 
206     /**
207      * {@inheritDoc}
208      */
209     @Override
210 public BindRequest setName( String name )
211     {
212         this.name = name;
213 
214         return this;
215     }
216 
217 
218     /**
219      * {@inheritDoc}
220      */
221     @Override
222     public Dn getDn()
223     {
224         return dn;
225     }
226 
227 
228     /**
229      * {@inheritDoc}
230      */
231     @Override
232     public BindRequest setDn( Dn dn )
233     {
234         this.dn = dn;
235         this.name = dn.getName();
236 
237         return this;
238     }
239 
240 
241     /**
242      * {@inheritDoc}
243      */
244     @Override
245     public boolean isVersion3()
246     {
247         return isVersion3;
248     }
249 
250 
251     /**
252      * {@inheritDoc}
253      */
254     @Override
255     public boolean getVersion3()
256     {
257         return isVersion3;
258     }
259 
260 
261     /**
262      * {@inheritDoc}
263      */
264     @Override
265     public BindRequest setVersion3( boolean version3 )
266     {
267         this.isVersion3 = version3;
268 
269         return this;
270     }
271 
272 
273     /**
274      * {@inheritDoc}
275      */
276     @Override
277     public BindRequest setMessageId( int messageId )
278     {
279         super.setMessageId( messageId );
280 
281         return this;
282     }
283 
284 
285     /**
286      * {@inheritDoc}
287      */
288     @Override
289     public BindRequest addControl( Control control )
290     {
291         return ( BindRequest ) super.addControl( control );
292     }
293 
294 
295     /**
296      * {@inheritDoc}
297      */
298     @Override
299     public BindRequest addAllControls( Control[] controls )
300     {
301         return ( BindRequest ) super.addAllControls( controls );
302     }
303 
304 
305     /**
306      * {@inheritDoc}
307      */
308     @Override
309     public BindRequest removeControl( Control control )
310     {
311         return ( BindRequest ) super.removeControl( control );
312     }
313 
314 
315     // -----------------------------------------------------------------------
316     // BindRequest Interface Method Implementations
317     // -----------------------------------------------------------------------
318     /**
319      * Gets the protocol response message type for this request which produces
320      * at least one response.
321      *
322      * @return the message type of the response.
323      */
324     @Override
325     public MessageTypeEnum getResponseType()
326     {
327         return MessageTypeEnum.BIND_RESPONSE;
328     }
329 
330 
331     /**
332      * The result containing response for this request.
333      *
334      * @return the result containing response for this request
335      */
336     @Override
337     public BindResponse getResultResponse()
338     {
339         if ( response == null )
340         {
341             response = new BindResponseImpl( getMessageId() );
342         }
343 
344         return response;
345     }
346 
347 
348     /**
349      * RFC 2251/4511 [Section 4.11]: Abandon, Bind, Unbind, and StartTLS operations
350      * cannot be abandoned.
351      */
352     @Override
353     public void abandon()
354     {
355         throw new UnsupportedOperationException( I18n.err( I18n.ERR_13506_CANNOT_ABANDON_OPERATION ) );
356     }
357 
358 
359     /**
360      * {@inheritDoc}
361      */
362     @Override
363     public boolean equals( Object obj )
364     {
365         if ( obj == this )
366         {
367             return true;
368         }
369 
370         if ( !( obj instanceof BindRequest ) )
371         {
372             return false;
373         }
374 
375         if ( !super.equals( obj ) )
376         {
377             return false;
378         }
379 
380         BindRequest req = ( BindRequest ) obj;
381 
382         if ( req.isSimple() != isSimple() )
383         {
384             return false;
385         }
386 
387         if ( req.isVersion3() != isVersion3() )
388         {
389             return false;
390         }
391 
392         String name1 = req.getName();
393         String name2 = getName();
394 
395         if ( Strings.isEmpty( name1 ) )
396         {
397             if ( !Strings.isEmpty( name2 ) )
398             {
399                 return false;
400             }
401         }
402         else
403         {
404             if ( Strings.isEmpty( name2 ) )
405             {
406                 return false;
407             }
408             else if ( !name2.equals( name1 ) )
409             {
410                 return false;
411             }
412         }
413 
414         Dn dn1 = req.getDn();
415         Dn dn2 = getDn();
416 
417         if ( Dn.isNullOrEmpty( dn1 ) )
418         {
419             if ( !Dn.isNullOrEmpty( dn2 ) )
420             {
421                 return false;
422             }
423         }
424         else
425         {
426             if ( Dn.isNullOrEmpty( dn2 ) )
427             {
428                 return false;
429             }
430             else if ( !dn1.equals( dn2 ) )
431             {
432                 return false;
433             }
434         }
435 
436         return Arrays.equals( req.getCredentials(), getCredentials() );
437     }
438 
439 
440     /**
441      * {@inheritDoc}
442      */
443     @Override
444     public int hashCode()
445     {
446         int hash = 37;
447         hash = hash * 17 + ( credentials == null ? 0 : hCredentials );
448         hash = hash * 17 + ( isSimple ? 0 : 1 );
449         hash = hash * 17 + ( isVersion3 ? 0 : 1 );
450         hash = hash * 17 + ( mechanism == null ? 0 : mechanism.hashCode() );
451         hash = hash * 17 + ( name == null ? 0 : name.hashCode() );
452         hash = hash * 17 + ( response == null ? 0 : response.hashCode() );
453         hash = hash * 17 + super.hashCode();
454 
455         return hash;
456     }
457 
458 
459     /**
460      * Get a String representation of a BindRequest
461      *
462      * @return A BindRequest String
463      */
464     @Override
465     public String toString()
466     {
467         StringBuilder sb = new StringBuilder();
468 
469         sb.append( "    BindRequest\n" );
470         sb.append( "        Version : '" ).append( isVersion3 ? "3" : "2" ).append( "'\n" );
471 
472         if ( isSimple )
473         {
474             if ( ( Strings.isEmpty( name ) && ( ( dn == null ) || dn.equals( Dn.EMPTY_DN ) ) ) )
475             {
476                 sb.append( "        Name : anonymous\n" );
477             }
478             else
479             {
480                 sb.append( "        Name : '" ).append( name ).append( "'\n" );
481                 sb.append( "        Simple authentication : '" ).append( "(omitted-for-safety)" ).append( "'\n" );
482             }
483         }
484         else
485         {
486             sb.append( "        Sasl credentials\n" );
487             sb.append( "            Mechanism :'" ).append( mechanism ).append( "'\n" );
488 
489             if ( credentials == null )
490             {
491                 sb.append( "            Credentials : null" );
492             }
493             else
494             {
495                 sb.append( "            Credentials : (omitted-for-safety)" );
496             }
497         }
498 
499         // The controls if any
500         return super.toString( sb.toString() );
501     }
502 }