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.server.core.jndi;
021    
022    
023    import java.util.Hashtable;
024    
025    import javax.naming.ConfigurationException;
026    import javax.naming.Context;
027    import javax.naming.NamingException;
028    
029    import org.apache.directory.server.i18n.I18n;
030    import org.apache.directory.shared.ldap.constants.AuthenticationLevel;
031    import org.apache.directory.shared.ldap.exception.LdapInvalidDnException;
032    import org.apache.directory.shared.ldap.name.DN;
033    import org.apache.directory.shared.ldap.util.StringTools;
034    
035    
036    /**
037     * A wrapper around a JNDI environment which checks for correct LDAP specific 
038     * environment settings.
039     *
040     * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
041     * @version $Rev: 924262 $
042     */
043    public class LdapJndiProperties
044    {
045        private static final String SASL_AUTHID = "java.naming.security.sasl.authorizationId";
046    
047        private DN providerDn;
048        private DN bindDn;
049        private String saslAuthId;
050        private AuthenticationLevel level;
051        private String saslMechanism;
052        private byte[] credentials;
053    
054    
055        public static AuthenticationLevel getAuthenticationLevel( Hashtable env ) throws NamingException
056        {
057            AuthenticationLevel level;
058            Object credobj = env.get( Context.SECURITY_CREDENTIALS );
059            Object authentication = env.get( Context.SECURITY_AUTHENTICATION );
060    
061            // -------------------------------------------------------------------
062            // Figure out and set the authentication level and mechanisms
063            // -------------------------------------------------------------------
064    
065            if ( authentication == null )
066            {
067                // if the property is not set but Context.SECURITY_CREDENTIALS is then SIMPLE
068                if ( credobj == null )
069                {
070                    level = AuthenticationLevel.NONE;
071                }
072                else
073                {
074                    level = AuthenticationLevel.SIMPLE;
075                }
076            }
077            else if ( !( authentication instanceof String ) )
078            {
079                throw new ConfigurationException( I18n.err( I18n.ERR_483, authentication.getClass(), 
080                    Context.SECURITY_AUTHENTICATION ) );
081            }
082            else
083            {
084                if ( AuthenticationLevel.NONE.toString().equals( authentication ) )
085                {
086                    level = AuthenticationLevel.NONE;
087                }
088                else if ( AuthenticationLevel.SIMPLE.toString().equals( authentication ) )
089                {
090                    level = AuthenticationLevel.SIMPLE;
091                }
092                else
093                {
094                    level = AuthenticationLevel.STRONG;
095                }
096            }
097    
098            return level;
099        }
100    
101    
102        public static LdapJndiProperties getLdapJndiProperties( Hashtable env ) throws NamingException
103        {
104            if ( env == null )
105            {
106                throw new ConfigurationException( "environment cannot be null" );
107            }
108    
109            LdapJndiProperties props = new LdapJndiProperties();
110            Object principal = env.get( Context.SECURITY_PRINCIPAL );
111            Object credobj = env.get( Context.SECURITY_CREDENTIALS );
112            Object authentication = env.get( Context.SECURITY_AUTHENTICATION );
113    
114            // -------------------------------------------------------------------
115            // check for the provider URL property 
116            // -------------------------------------------------------------------
117    
118            if ( !env.containsKey( Context.PROVIDER_URL ) )
119            {
120                String msg = I18n.err( I18n.ERR_484, Context.PROVIDER_URL );
121                throw new ConfigurationException( msg );
122            }
123    
124            String url = ( String ) env.get( Context.PROVIDER_URL );
125    
126            if ( url == null )
127            {
128                String msg = I18n.err( I18n.ERR_485, Context.PROVIDER_URL );
129                throw new ConfigurationException( msg );
130            }
131    
132            if ( url.trim().equals( "" ) )
133            {
134                props.providerDn = DN.EMPTY_DN;
135            }
136            else
137            {
138                try
139                {
140                    props.providerDn = new DN( url );
141                }
142                catch ( LdapInvalidDnException lide )
143                {
144                    String msg = I18n.err( I18n.ERR_733, url );
145                    throw new ConfigurationException( msg );
146                }
147            }
148    
149            // -------------------------------------------------------------------
150            // Figure out and set the authentication level and mechanisms
151            // -------------------------------------------------------------------
152    
153            if ( authentication == null )
154            {
155                // if the property is not set but Context.SECURITY_CREDENTIALS is then SIMPLE
156                if ( credobj == null )
157                {
158                    props.level = AuthenticationLevel.NONE;
159                }
160                else
161                {
162                    props.level = AuthenticationLevel.SIMPLE;
163                }
164            }
165            else if ( !( authentication instanceof String ) )
166            {
167                throw new ConfigurationException( I18n.err( I18n.ERR_483, authentication.getClass(), 
168                    Context.SECURITY_AUTHENTICATION ) );
169            }
170            else
171            {
172                if ( AuthenticationLevel.NONE.toString().equals( authentication ) )
173                {
174                    props.level = AuthenticationLevel.NONE;
175                }
176                else if ( AuthenticationLevel.SIMPLE.toString().equals( authentication ) )
177                {
178                    props.level = AuthenticationLevel.SIMPLE;
179                }
180                else
181                {
182                    props.level = AuthenticationLevel.STRONG;
183                    props.saslMechanism = ( String ) authentication;
184    //                String[] mechList = ( ( String ) authentication ).trim().split( " " );
185    //                for ( String mech : mechList )
186    //                {
187    //                    if ( !mech.trim().equals( "" ) )
188    //                    {
189    //                        props.mechanisms.add( mech );
190    //                    }
191    //                }
192                }
193            }
194    
195            // -------------------------------------------------------------------
196            // Figure out and set the security principal bindDn and saslAuthId
197            // -------------------------------------------------------------------
198    
199            if ( principal == null && props.level == AuthenticationLevel.SIMPLE )
200            {
201                throw new ConfigurationException( I18n.err( I18n.ERR_487, Context.SECURITY_PRINCIPAL ) );
202            }
203            else if ( principal == null && props.level == AuthenticationLevel.NONE )
204            {
205                props.bindDn = DN.EMPTY_DN;
206            }
207            else if ( !( principal instanceof String ) )
208            {
209                throw new ConfigurationException( I18n.err( I18n.ERR_483, principal.getClass(), Context.SECURITY_PRINCIPAL ) );
210            }
211            else if ( ( ( String ) principal ).trim().equals( "" ) )
212            {
213                props.bindDn = DN.EMPTY_DN;
214            }
215            else
216            {
217                try
218                {
219                    props.providerDn = new DN( ( String ) principal );
220                }
221                catch ( LdapInvalidDnException lide )
222                {
223                    String msg = I18n.err( I18n.ERR_733, principal );
224                    throw new ConfigurationException( msg );
225                }
226    
227            }
228            
229    
230            if ( env.get( SASL_AUTHID ) != null && props.level == AuthenticationLevel.STRONG )
231            {
232                Object obj = env.get( SASL_AUTHID );
233                if ( obj instanceof String )
234                {
235                    props.saslAuthId = ( String ) obj;
236                }
237                else
238                {
239                    throw new ConfigurationException( I18n.err( I18n.ERR_483, obj.getClass(), SASL_AUTHID ) );
240                }
241                props.saslAuthId = ( String ) principal;
242            }
243    
244            // -------------------------------------------------------------------
245            // Figure out the credentials
246            // -------------------------------------------------------------------
247    
248            if ( props.level == AuthenticationLevel.SIMPLE && credobj == null )
249            {
250                throw new ConfigurationException( I18n.err( I18n.ERR_489 ) );
251            }
252            else if ( credobj != null )
253            {
254                if ( credobj instanceof String )
255                {
256                    props.credentials = StringTools.getBytesUtf8( ( String ) credobj );
257                }
258                else if ( credobj instanceof byte[] )
259                {
260                    props.credentials = ( byte[] ) credobj;
261                }
262                else
263                {
264                    throw new ConfigurationException( I18n.err( I18n.ERR_483, credobj.getClass(), Context.SECURITY_CREDENTIALS ) );
265                }
266            }
267    
268            return props;
269        }
270    
271    
272        public DN getBindDn()
273        {
274            return bindDn;
275        }
276    
277    
278        public DN getProviderDn()
279        {
280            return providerDn;
281        }
282    
283    
284        public String getSaslAuthId()
285        {
286            return saslAuthId;
287        }
288    
289    
290        public AuthenticationLevel getAuthenticationLevel()
291        {
292            return level;
293        }
294    
295    
296        public String getSaslMechanism()
297        {
298            return saslMechanism;
299        }
300    
301    
302        public byte[] getCredentials()
303        {
304            return credentials;
305        }
306    }