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