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-10 23:37:30 +0100 (Wed, 10 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 }