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.Asn1Object;
027 import org.apache.directory.shared.asn1.ber.tlv.TLV;
028 import org.apache.directory.shared.asn1.ber.tlv.Value;
029 import org.apache.directory.shared.asn1.codec.EncoderException;
030 import org.apache.directory.shared.i18n.I18n;
031 import org.apache.directory.shared.ldap.codec.LdapConstants;
032 import org.apache.directory.shared.ldap.util.StringTools;
033 import org.slf4j.Logger;
034 import org.slf4j.LoggerFactory;
035
036
037 /**
038 * A ldapObject which stores the SASL authentication of a BindRequest.
039 *
040 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
041 * @version $Rev: 912399 $, $Date: 2010-02-21 21:52:31 +0100 (Dim, 21 fév 2010) $,
042 */
043 public class SaslCredentials extends LdapAuthentication
044 {
045 /** The logger */
046 private static Logger log = LoggerFactory.getLogger( SimpleAuthentication.class );
047
048 /** Speedup for logs */
049 private static final boolean IS_DEBUG = log.isDebugEnabled();
050
051 // ~ Instance fields
052 // ----------------------------------------------------------------------------
053
054 /**
055 * Any mechanism defined in RFC 2222 : KERBEROS_V4, GSSAPI, SKEY, EXTERNAL
056 */
057 private String mechanism;
058
059 /** The mechanism bytes */
060 private byte[] mechanismBytes;
061
062 /** optional credentials of the user */
063 private byte[] credentials;
064
065 /** The mechanism length */
066 private int mechanismLength;
067
068 /** The credentials length */
069 private int credentialsLength;
070
071
072 /**
073 * @see Asn1Object#Asn1Object
074 */
075 public SaslCredentials()
076 {
077 super();
078 }
079
080 // ~ Methods
081 // ------------------------------------------------------------------------------------
082
083 /**
084 * Get the credentials
085 *
086 * @return The credentials
087 */
088 public byte[] getCredentials()
089 {
090 if ( credentials == null )
091 {
092 return null;
093 }
094
095 final byte[] copy = new byte[ credentials.length ];
096 System.arraycopy( credentials, 0, copy, 0, credentials.length );
097 return copy;
098 }
099
100
101 /**
102 * Set the credentials
103 *
104 * @param credentials The credentials
105 */
106 public void setCredentials( byte[] credentials )
107 {
108 if ( credentials != null )
109 {
110 this.credentials = new byte[ credentials.length ];
111 System.arraycopy( credentials, 0, this.credentials, 0, credentials.length );
112 } else {
113 this.credentials = null;
114 }
115 }
116
117
118 /**
119 * Get the mechanism
120 *
121 * @return The mechanism
122 */
123 public String getMechanism()
124 {
125
126 return ( ( mechanism == null ) ? null : mechanism );
127 }
128
129
130 /**
131 * Set the mechanism
132 *
133 * @param mechanism The mechanism
134 */
135 public void setMechanism( String mechanism )
136 {
137 this.mechanism = mechanism;
138 }
139
140
141 /**
142 * Compute the Sasl authentication length
143 *
144 * Sasl authentication :
145 *
146 * 0xA3 L1
147 * 0x04 L2 mechanism
148 * [0x04 L3 credentials]
149 *
150 * L2 = Length(mechanism)
151 * L3 = Length(credentials)
152 * L1 = L2 + L3
153 *
154 * Length(Sasl authentication) = Length(0xA3) + Length(L1) +
155 * Length(0x04) + Length(L2) + Length(mechanism)
156 * [+ Length(0x04) + Length(L3) + Length(credentials)]
157 */
158 public int computeLength()
159 {
160 mechanismBytes = StringTools.getBytesUtf8( mechanism );
161 mechanismLength = 1 + TLV.getNbBytes( mechanismBytes.length ) + mechanismBytes.length;
162 credentialsLength = 0;
163
164 if ( credentials != null )
165 {
166 credentialsLength = 1 + TLV.getNbBytes( credentials.length ) + credentials.length;
167 }
168
169 int saslLength = 1 + TLV.getNbBytes( mechanismLength + credentialsLength ) + mechanismLength
170 + credentialsLength;
171
172 if ( IS_DEBUG )
173 {
174 log.debug( "SASL Authentication length : {}", Integer.valueOf( saslLength ) );
175 }
176
177 return saslLength;
178 }
179
180
181 /**
182 * Encode the sasl authentication to a PDU.
183 *
184 * SimpleAuthentication :
185 * 0xA3 L1
186 * 0x04 L2 mechanism
187 * [0x04 L3 credentials]
188 *
189 * @param buffer The buffer where to put the PDU
190 * @return The PDU.
191 */
192 public ByteBuffer encode( ByteBuffer buffer ) throws EncoderException
193 {
194 if ( buffer == null )
195 {
196 log.error( I18n.err( I18n.ERR_04023 ) );
197 throw new EncoderException( I18n.err( I18n.ERR_04023 ) );
198 }
199
200 try
201 {
202 // The saslAuthentication Tag
203 buffer.put( ( byte ) LdapConstants.BIND_REQUEST_SASL_TAG );
204
205 buffer.put( TLV.getBytes( mechanismLength + credentialsLength ) );
206
207 Value.encode( buffer, mechanism );
208
209 if ( credentials != null )
210 {
211 Value.encode( buffer, credentials );
212 }
213 }
214 catch ( BufferOverflowException boe )
215 {
216 log.error( I18n.err( I18n.ERR_04005 ) );
217 throw new EncoderException( I18n.err( I18n.ERR_04005) );
218 }
219
220 return buffer;
221 }
222
223
224 /**
225 * Get a String representation of a SaslCredential
226 *
227 * @return A SaslCredential String
228 */
229 public String toString()
230 {
231 StringBuilder sb = new StringBuilder();
232
233 sb.append( " Sasl credentials\n" );
234 sb.append( " Mechanism :'" ).append( mechanism ).append( '\'' );
235
236 if ( credentials != null )
237 {
238 sb.append( "\n Credentials :'" ).
239 append( StringTools.dumpBytes( credentials ) ).
240 append( '\'' );
241 }
242
243 return sb.toString();
244 }
245 }