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