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.codec.bind;
021
022
023 import java.nio.BufferOverflowException;
024 import java.nio.ByteBuffer;
025
026 import org.apache.directory.shared.asn1.ber.tlv.TLV;
027 import org.apache.directory.shared.asn1.ber.tlv.Value;
028 import org.apache.directory.shared.asn1.codec.EncoderException;
029 import org.apache.directory.shared.ldap.codec.LdapConstants;
030 import org.apache.directory.shared.ldap.codec.LdapMessageCodec;
031 import org.apache.directory.shared.ldap.name.LdapDN;
032 import org.apache.directory.shared.ldap.util.StringTools;
033
034
035 /**
036 * A BindRequest ldapObject. It's a sub-class of Asn1Object, and it extends the
037 * Asn1Object class to be seen as a member of the LdapMessage CHOICE.
038 *
039 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
040 * @version $Rev: 764131 $, $Date: 2009-04-11 03:03:00 +0200 (Sam, 11 avr 2009) $,
041 */
042 public class BindRequestCodec extends LdapMessageCodec
043 {
044 // ~ Instance fields
045 // ----------------------------------------------------------------------------
046
047 /** The protocol Version to use. Should be 3 */
048 private int version;
049
050 /** The name of the user requesting a bind */
051 private LdapDN name;
052
053 /** The authentication used to bind the user */
054 private LdapAuthentication authentication;
055
056 /** The bind request length */
057 private int bindRequestLength;
058
059 /**
060 * Creates a new BindRequest object.
061 */
062 public BindRequestCodec()
063 {
064 super();
065 }
066
067 /**
068 * Get the message type
069 *
070 * @return Returns the type.
071 */
072 public int getMessageType()
073 {
074 return LdapConstants.BIND_REQUEST;
075 }
076
077
078 /**
079 * Get the user authentication
080 *
081 * @return The user authentication
082 */
083 public LdapAuthentication getAuthentication()
084 {
085 return authentication;
086 }
087
088
089 /**
090 * Get the user simple authentication
091 *
092 * @return The simple user authentication
093 */
094 public SimpleAuthentication getSimpleAuthentication()
095 {
096 return ( SimpleAuthentication ) authentication;
097 }
098
099
100 /**
101 * Get the user sasl authentication
102 *
103 * @return The sasl user authentication
104 */
105 public SaslCredentials getSaslAuthentication()
106 {
107 return ( SaslCredentials ) authentication;
108 }
109
110
111 /**
112 * Set the user authentication
113 *
114 * @param authentication The user authentication
115 */
116 public void setAuthentication( LdapAuthentication authentication )
117 {
118 this.authentication = authentication;
119 }
120
121
122 /**
123 * Get the user name
124 *
125 * @return The user name
126 */
127 public LdapDN getName()
128 {
129 return name;
130 }
131
132
133 /**
134 * Set the user name
135 *
136 * @param name The user name
137 */
138 public void setName( LdapDN name )
139 {
140 this.name = name;
141 }
142
143
144 /**
145 * Get the protocol version
146 *
147 * @return The protocol version
148 */
149 public int getVersion()
150 {
151 return version;
152 }
153
154
155 /**
156 * Check if the Ldap version in use is 3
157 *
158 * @return true if the ldap version is 3
159 */
160 public boolean isLdapV3()
161 {
162 return version == 3;
163 }
164
165
166 /**
167 * Set the protocol version
168 *
169 * @param version The protocol version
170 */
171 public void setVersion( int version )
172 {
173 this.version = version;
174 }
175
176
177 /**
178 * Compute the BindRequest length
179 *
180 * BindRequest :
181 * 0x60 L1
182 * |
183 * +--> 0x02 0x01 (1..127) version
184 * +--> 0x04 L2 name
185 * +--> authentication
186 *
187 * L2 = Length(name)
188 * L3/4 = Length(authentication)
189 * Length(BindRequest) = Length(0x60) + Length(L1) + L1 + Length(0x02) + 1 + 1 +
190 * Length(0x04) + Length(L2) + L2 + Length(authentication)
191 */
192 public int computeLength()
193 {
194 bindRequestLength = 1 + 1 + 1; // Initialized with version
195
196 // The name
197 bindRequestLength += 1 + TLV.getNbBytes( LdapDN.getNbBytes( name ) ) + LdapDN.getNbBytes( name );
198
199 // The authentication
200 bindRequestLength += authentication.computeLength();
201
202 // Return the result.
203 return 1 + TLV.getNbBytes( bindRequestLength ) + bindRequestLength;
204 }
205
206
207 /**
208 * Encode the BindRequest message to a PDU.
209 *
210 * BindRequest :
211 *
212 * 0x60 LL
213 * 0x02 LL version 0x80 LL simple
214 * 0x04 LL name /
215 * authentication.encode()
216 * \ 0x83 LL mechanism [0x04 LL credential]
217 *
218 *
219 * @param buffer The buffer where to put the PDU
220 * @return The PDU.
221 */
222 public ByteBuffer encode( ByteBuffer buffer ) throws EncoderException
223 {
224 if ( buffer == null )
225 {
226 throw new EncoderException( "Cannot put a PDU in a null buffer !" );
227 }
228
229 try
230 {
231 // The BindRequest Tag
232 buffer.put( LdapConstants.BIND_REQUEST_TAG );
233 buffer.put( TLV.getBytes( bindRequestLength ) );
234
235 }
236 catch ( BufferOverflowException boe )
237 {
238 throw new EncoderException( "The PDU buffer size is too small !" );
239 }
240
241 // The version
242 Value.encode( buffer, version );
243
244 // The name
245 Value.encode( buffer, LdapDN.getBytes( name ) );
246
247 // The authentication
248 authentication.encode( buffer );
249
250 return buffer;
251 }
252
253
254 /**
255 * Get a String representation of a BindRequest
256 *
257 * @return A BindRequest String
258 */
259 public String toString()
260 {
261 StringBuffer sb = new StringBuffer();
262
263 sb.append( " BindRequest\n" );
264 sb.append( " Version : '" ).append( version ).append( "'\n" );
265
266 if ( ( null == name ) || StringTools.isEmpty( name.toString() ) )
267 {
268 sb.append( " Name : anonymous\n" );
269 }
270 else
271 {
272 sb.append( " Name : '" ).append( name ).append( "'\n" );
273
274 if ( authentication instanceof SimpleAuthentication )
275 {
276 sb.append( " Simple authentication : '" ).append( authentication ).append( "'\n" );
277 }
278 else
279 {
280 sb.append( authentication );
281 }
282 }
283
284 return sb.toString();
285 }
286
287 /* Used only for test perfs
288 public static void main( String[] args ) throws Exception
289 {
290 Asn1Decoder ldapDecoder = new LdapDecoder();
291
292 ByteBuffer stream = ByteBuffer.allocate( 0x52 );
293 stream.put( new byte[]
294 {
295 0x30, 0x50, // LDAPMessage ::=SEQUENCE {
296 0x02, 0x01, 0x01, // messageID MessageID
297 0x60, 0x2E, // CHOICE { ..., bindRequest BindRequest, ...
298 // BindRequest ::= APPLICATION[0] SEQUENCE {
299 0x02, 0x01, 0x03, // version INTEGER (1..127),
300 0x04, 0x1F, // name LDAPDN,
301 'u', 'i', 'd', '=', 'a', 'k', 'a', 'r', 'a', 's', 'u', 'l', 'u', ',', 'd', 'c', '=', 'e', 'x', 'a',
302 'm', 'p', 'l', 'e', ',', 'd', 'c', '=', 'c', 'o', 'm',
303 ( byte ) 0x80, 0x08, // authentication AuthenticationChoice
304 // AuthenticationChoice ::= CHOICE { simple [0] OCTET STRING,
305 // ...
306 'p', 'a', 's', 's', 'w', 'o', 'r', 'd',
307 ( byte ) 0xA0, 0x1B, // A control
308 0x30, 0x19,
309 0x04, 0x17,
310 0x32, 0x2E, 0x31, 0x36, 0x2E, 0x38, 0x34, 0x30, 0x2E, 0x31, 0x2E, 0x31, 0x31, 0x33, 0x37, 0x33,
311 0x30, 0x2E, 0x33, 0x2E, 0x34, 0x2E, 0x32
312 } );
313
314 stream.flip();
315
316 // Allocate a LdapMessage Container
317 IAsn1Container ldapMessageContainer = new LdapMessageContainer();
318
319 // Decode the BindRequest PDU
320 try
321 {
322 long t0 = System.currentTimeMillis();
323 for ( int i = 0; i < 10000000; i++ )
324 {
325 ldapDecoder.decode( stream, ldapMessageContainer );
326 ( ( LdapMessageContainer ) ldapMessageContainer).clean();
327 stream.flip();
328 }
329 long t1 = System.currentTimeMillis();
330 System.out.println( "Delta = " + ( t1 - t0 ) );
331
332 ldapDecoder.decode( stream, ldapMessageContainer );
333 }
334 catch ( DecoderException de )
335 {
336 de.printStackTrace();
337 }
338 catch ( NamingException ne )
339 {
340 ne.printStackTrace();
341 }
342 }
343 */
344 }