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 */
020 package org.apache.directory.shared.ldap.message;
021
022
023 import java.util.Arrays;
024
025 import org.apache.directory.shared.ldap.name.LdapDN;
026 import org.apache.directory.shared.ldap.util.StringTools;
027
028
029 /**
030 * Bind protocol operation request which authenticates and begins a client
031 * session. Does not yet contain interfaces for SASL authentication mechanisms.
032 *
033 * @author <a href="mailto:dev@directory.apache.org"> Apache Directory Project</a>
034 * @version $Rev: 764131 $
035 */
036 public class BindRequestImpl extends AbstractAbandonableRequest implements InternalBindRequest
037 {
038 static final long serialVersionUID = 7945504184130380071L;
039
040 /**
041 * Distinguished name identifying the name of the authenticating subject -
042 * defaults to the empty string
043 */
044 private LdapDN name;
045
046 /** The passwords, keys or tickets used to verify user identity */
047 private byte[] credentials;
048
049 /** A storage for credential hashCode */
050 private int hCredentials;
051
052 /** The mechanism used to decode user identity */
053 private String mechanism;
054
055 /** Simple vs. SASL authentication mode flag */
056 private boolean isSimple = true;
057
058 /** Bind behavoir exhibity by protocol version */
059 private boolean isVersion3 = true;
060
061 public InternalBindResponse response;
062
063
064 // ------------------------------------------------------------------------
065 // Constructors
066 // ------------------------------------------------------------------------
067
068 /**
069 * Creates an BindRequest implementation to bind to an LDAP server.
070 *
071 * @param id
072 * the sequence identifier of the BindRequest message.
073 */
074 public BindRequestImpl(final int id)
075 {
076 super( id, TYPE );
077 hCredentials = 0;
078 }
079
080
081 // -----------------------------------------------------------------------
082 // BindRequest Interface Method Implementations
083 // -----------------------------------------------------------------------
084
085 /**
086 * Checks to see if the authentication mechanism is simple and not SASL
087 * based.
088 *
089 * @return true if the mechanism is simple false if it is SASL based.
090 */
091 public boolean isSimple()
092 {
093 return isSimple;
094 }
095
096
097 /**
098 * Checks to see if the authentication mechanism is simple and not SASL
099 * based.
100 *
101 * @return true if the mechanism is simple false if it is SASL based.
102 */
103 public boolean getSimple()
104 {
105 return isSimple;
106 }
107
108
109 /**
110 * Sets the authentication mechanism to simple or to SASL based
111 * authentication.
112 *
113 * @param isSimple
114 * true if authentication is simple, false otherwise.
115 */
116 public void setSimple( boolean isSimple )
117 {
118 this.isSimple = isSimple;
119 }
120
121
122 /**
123 * Gets the simple credentials associated with a simple authentication
124 * attempt or null if this request uses SASL authentication mechanisms.
125 *
126 * @return null if the mechanism is SASL or the credentials if it is simple.
127 */
128 public byte[] getCredentials()
129 {
130 return credentials;
131 }
132
133
134 /**
135 * Sets the simple credentials associated with a simple authentication
136 * attempt ignored if this request uses SASL authentication mechanisms.
137 *
138 * @param credentials
139 * the credentials if authentication is simple, null otherwise
140 */
141 public void setCredentials( byte[] credentials )
142 {
143 if ( credentials != null )
144 {
145 this.credentials = new byte[ credentials.length ];
146 System.arraycopy( credentials, 0, this.credentials, 0, credentials.length );
147 } else {
148 this.credentials = null;
149 }
150
151 if ( credentials != null )
152 {
153 hCredentials = 0;
154
155 for ( byte b:credentials )
156 {
157 hCredentials = hCredentials*31 + b;
158 }
159 }
160 else
161 {
162 hCredentials = 0;
163 }
164 }
165
166
167 /**
168 * Gets the mechanism if this request uses SASL authentication mechanisms.
169 *
170 * @return The mechanism if SASL.
171 */
172 public String getSaslMechanism()
173 {
174 return mechanism;
175 }
176
177
178 /**
179 * Sets the mechanism associated with a SASL authentication
180 *
181 * @param mechanism
182 * the mechanism otherwise
183 */
184 public void setSaslMechanism( String mechanism )
185 {
186 this.mechanism = mechanism;
187 }
188
189
190 /**
191 * Gets the distinguished name of the subject in this authentication
192 * request. This field may take on a null value (a zero length string) for
193 * the purposes of anonymous binds, when authentication has been performed
194 * at a lower layer, or when using SASL credentials with a mechanism that
195 * includes the LDAPDN in the credentials.
196 *
197 * @return the DN of the authenticating user.
198 */
199 public LdapDN getName()
200 {
201 return name;
202 }
203
204
205 /**
206 * Sets the distinguished name of the subject in this authentication
207 * request. This field may take on a null value (or a zero length string)
208 * for the purposes of anonymous binds, when authentication has been
209 * performed at a lower layer, or when using SASL credentials with a
210 * mechanism that includes the LDAPDN in the credentials.
211 *
212 * @param name
213 * the DN of the authenticating user - leave null for annonymous
214 * user.
215 */
216 public void setName( LdapDN name )
217 {
218 this.name = name;
219 }
220
221
222 /**
223 * Checks to see if the Ldap v3 protocol is used. Normally this would
224 * extract a version number from the bind request sent by the client
225 * indicating the version of the protocol to be used in this protocol
226 * session. The integer is either a 2 or a 3 at the moment. We thought it
227 * was better to just check if the protocol used is 3 or not rather than use
228 * an type-safe enumeration type for a binary value. If an LDAPv4 comes out
229 * then we shall convert the return type to a type safe enumeration.
230 *
231 * @return true if client using version 3 false if it is version 2.
232 */
233 public boolean isVersion3()
234 {
235 return isVersion3;
236 }
237
238
239 /**
240 * Gets whether or not the Ldap v3 protocol is used. Normally this would
241 * extract a version number from the bind request sent by the client
242 * indicating the version of the protocol to be used in this protocol
243 * session. The integer is either a 2 or a 3 at the moment. We thought it
244 * was better to just check if the protocol used is 3 or not rather than use
245 * an type-safe enumeration type for a binary value. If an LDAPv4 comes out
246 * then we shall convert the return type to a type safe enumeration.
247 *
248 * @return true if client using version 3 false if it is version 2.
249 */
250 public boolean getVersion3()
251 {
252 return isVersion3;
253 }
254
255
256 /**
257 * Sets whether or not the LDAP v3 or v2 protocol is used. Normally this
258 * would extract a version number from the bind request sent by the client
259 * indicating the version of the protocol to be used in this protocol
260 * session. The integer is either a 2 or a 3 at the moment. We thought it
261 * was better to just check if the protocol used is 3 or not rather than use
262 * an type-safe enumeration type for a binary value. If an LDAPv4 comes out
263 * then we shall convert the return type to a type safe enumeration.
264 *
265 * @param isVersion3
266 * if true the client will be exhibiting version 3 bind behavoir,
267 * if false is used version 2 behavoir will be exhibited.
268 */
269 public void setVersion3( boolean isVersion3 )
270 {
271 this.isVersion3 = isVersion3;
272 }
273
274
275 // -----------------------------------------------------------------------
276 // BindRequest Interface Method Implementations
277 // -----------------------------------------------------------------------
278
279 /**
280 * Gets the protocol response message type for this request which produces
281 * at least one response.
282 *
283 * @return the message type of the response.
284 */
285 public MessageTypeEnum getResponseType()
286 {
287 return RESP_TYPE;
288 }
289
290
291 /**
292 * The result containing response for this request.
293 *
294 * @return the result containing response for this request
295 */
296 public InternalResultResponse getResultResponse()
297 {
298 if ( response == null )
299 {
300 response = new BindResponseImpl( getMessageId() );
301 }
302
303 return response;
304 }
305
306 /**
307 * @see Object#equals(Object)
308 */
309 public boolean equals( Object obj )
310 {
311 if ( obj == this )
312 {
313 return true;
314 }
315
316 if ( ( obj == null ) || !( obj instanceof InternalBindRequest ) )
317 {
318 return false;
319 }
320
321 if ( !super.equals( obj ) )
322 {
323 return false;
324 }
325
326 InternalBindRequest req = ( InternalBindRequest ) obj;
327
328 if ( req.isSimple() != isSimple() )
329 {
330 return false;
331 }
332
333 if ( req.isVersion3() != isVersion3() )
334 {
335 return false;
336 }
337
338 LdapDN dn1 = req.getName();
339 LdapDN dn2 = getName();
340
341 if ( dn1 == null )
342 {
343 if ( dn2 != null )
344 {
345 return false;
346 }
347 }
348 else
349 {
350 if ( dn2 == null )
351 {
352 return false;
353 }
354 else if ( !dn1.equals( dn2 ) )
355 {
356 return false;
357 }
358
359 }
360
361 if ( !Arrays.equals( req.getCredentials(), getCredentials() ) )
362 {
363 return false;
364 }
365
366 return true;
367 }
368
369 /**
370 * @see Object#hashCode()
371 * @return the instance's hash code
372 */
373 public int hashCode()
374 {
375 int hash = 37;
376 hash = hash*17 + ( credentials == null ? 0 : hCredentials );
377 hash = hash*17 + ( isSimple ? 0 : 1 );
378 hash = hash*17 + ( isVersion3 ? 0 : 1 );
379 hash = hash*17 + ( mechanism == null ? 0 : mechanism.hashCode() );
380 hash = hash*17 + ( name == null ? 0 : name.hashCode() );
381 hash = hash*17 + ( response == null ? 0 : response.hashCode() );
382 hash = hash*17 + super.hashCode();
383
384 return hash;
385 }
386
387 /**
388 * Get a String representation of a BindRequest
389 *
390 * @return A BindRequest String
391 */
392 public String toString()
393 {
394 StringBuffer sb = new StringBuffer();
395 sb.append( " BindRequest\n" );
396 sb.append( " Version : '" ).append( isVersion3 ? "3" : "2" ).append( "'\n" );
397
398 if ( StringTools.isEmpty( name.toString() ) && isSimple )
399 {
400 sb.append( " Name : anonymous\n" );
401 }
402 else
403 {
404 sb.append( " Name : '" ).append( name.toString() ).append( "'\n" );
405
406 if ( isSimple )
407 {
408 sb.append( " Simple authentication : '" ).append( StringTools.utf8ToString( credentials ) )
409 .append( '/' ).append( StringTools.dumpBytes( credentials ) ).append( "'\n" );
410 }
411 else
412 {
413 sb.append( " Sasl credentials\n" );
414 sb.append( " Mechanism :'" ).append( mechanism ).append( "'\n" );
415
416 if ( credentials == null )
417 {
418 sb.append( " Credentials : null" );
419 }
420 else
421 {
422 sb.append( " Credentials : '" ).
423 append( StringTools.utf8ToString( credentials ) ).
424 append( '/' ).
425 append( StringTools.dumpBytes( credentials ) ).
426 append( "'\n" );
427 }
428 }
429 }
430
431 return sb.toString();
432 }
433
434
435 /**
436 * RFC 2251 [Section 4.11]: Abandon, Bind, Unbind, and StartTLS operations
437 * cannot be abandoned.
438 */
439 public void abandon()
440 {
441 throw new UnsupportedOperationException(
442 "RFC 2251 [Section 4.11]: Abandon, Bind, Unbind, and StartTLS operations cannot be abandoned. " );
443 }
444 }