View Javadoc
1   /*
2    * Copyright 2001-2009 The Apache Software Foundation.
3    * 
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * 
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.apache.juddi.v3.auth;
17  
18  import java.util.Hashtable;
19  
20  import javax.naming.Context;
21  import javax.naming.NamingException;
22  import javax.naming.ldap.InitialLdapContext;
23  import javax.naming.ldap.LdapContext;
24  import javax.persistence.EntityManager;
25  import javax.persistence.EntityTransaction;
26  import javax.xml.ws.WebServiceContext;
27  
28  import org.apache.commons.logging.Log;
29  import org.apache.commons.logging.LogFactory;
30  
31  import org.apache.juddi.config.AppConfig;
32  import org.apache.juddi.config.PersistenceManager;
33  import org.apache.juddi.config.Property;
34  import org.apache.juddi.model.Publisher;
35  import org.apache.juddi.model.UddiEntityPublisher;
36  import org.apache.juddi.v3.error.AuthenticationException;
37  import org.apache.juddi.v3.error.ErrorMessage;
38  import org.apache.juddi.v3.error.FatalErrorException;
39  import org.apache.juddi.v3.error.UnknownUserException;
40  
41  import org.apache.commons.configuration.ConfigurationException;
42  
43  /**
44   * This is a implementation of jUDDI's Authenticator interface, that uses the
45   * LDAP. z
46   * 
47   * Usage:
48   * 
49   * To use this class you must add the following properties to the
50   * juddiv3.properties file:
51   * 
52   * # The LDAP Authenticator
53   * juddi.authenticator=org.apache.juddi.v3.auth.LdapSimpleAuthenticator
54   * 
55   * # LDAP authentication URL
56   * juddi.authenticator.url=ldap://localhost:389
57   *
58   * This authenticator assumes that the publisher username is the same as the LDAP 
59   * principal name, which may not be the case as the LDAP principal might be a bind name.
60   * This class could easily be extended so that the uid of the LDAP authenticated user is
61   * used, or to authenticate by group.<br><br>
62   *
63   * This class was tested with OpenLDAP.<br>
64   * <br> See properties:
65   *  {@link org.apache.juddi.config.Property#JUDDI_AUTHENTICATOR_INITIAL_CONTEXT JUDDI_AUTHENTICATOR_INITIAL_CONTEXT}
66   *  {@link org.apache.juddi.config.Property#JUDDI_AUTHENTICATOR_STYLE JUDDI_AUTHENTICATOR_STYLE}
67   *
68   * @author <a href="mailto:tcunning@apache.org">Tom Cunningham</a>
69   * @author <a href="mailto:gunnlaugursig@gmail.com">Gunnlaugur SigurĂ°sson</a>
70   * @author <a href="mailto:alexoree@apache.org">Alex O'Ree</a>
71   * 
72   * @since 3.2, all values are now configurable
73   * @see Property
74   * 
75   */
76  public class LdapSimpleAuthenticator implements Authenticator {
77      private Log logger = LogFactory.getLog(this.getClass());
78  
79      private LdapContext ctx = null;
80      //this needs to be a Hashtable, HashMap won't work here
81      private Hashtable<String, String> env = null;
82      private String url = null;
83      
84      private static final String DEFAULT_URL = "ldap://localhost:389";
85      
86      public LdapSimpleAuthenticator() throws NamingException, ConfigurationException {
87      	String authURL = null;
88      	try {
89      		authURL = AppConfig.getConfiguration().getString(Property.JUDDI_AUTHENTICATOR_URL, DEFAULT_URL);
90      	} catch (ConfigurationException ce) {
91      		logger.error("Configuration exception occurred retrieving: " + Property.JUDDI_AUTHENTICATOR_URL);
92      		throw new NamingException(Property.JUDDI_AUTHENTICATOR_URL + " missing from config or config is not available.");
93      	}
94      	init(authURL);
95      }
96      
97      public LdapSimpleAuthenticator(String url) throws NamingException, ConfigurationException {
98      	init(url);
99      }
100 
101     public void init(String url) throws NamingException, ConfigurationException {
102         env = new Hashtable<String, String>();
103         env.put(Context.INITIAL_CONTEXT_FACTORY, AppConfig.getConfiguration().getString(Property.JUDDI_AUTHENTICATOR_INITIAL_CONTEXT, "com.sun.jndi.ldap.LdapCtxFactory"));
104         env.put(Context.SECURITY_AUTHENTICATION, AppConfig.getConfiguration().getString(Property.JUDDI_AUTHENTICATOR_STYLE, "simple"));
105         env.put(Context.PROVIDER_URL, url); // organization ldap url, example ldap://localhost:389
106 
107         this.url = url;
108         
109         try {
110             ctx = new InitialLdapContext(env, null);
111         } catch (NamingException e) {
112             logger.error("Naming exception " + e);
113             throw e;
114         }
115     }
116     
117     public String authenticate(String authorizedName, String cred)
118             throws AuthenticationException, FatalErrorException {
119         if (authorizedName == null || "".equals(authorizedName)) {
120             throw new UnknownUserException(new ErrorMessage("errors.auth.NoPublisher", authorizedName));
121         }
122 
123         int MaxBindingsPerService = -1;
124         int MaxServicesPerBusiness = -1;
125         int MaxTmodels = -1;
126         int MaxBusinesses = -1;
127         try {
128                 MaxBindingsPerService = AppConfig.getConfiguration().getInt(Property.JUDDI_MAX_BINDINGS_PER_SERVICE, -1);
129                 MaxServicesPerBusiness = AppConfig.getConfiguration().getInt(Property.JUDDI_MAX_SERVICES_PER_BUSINESS, -1);
130                 MaxTmodels = AppConfig.getConfiguration().getInt(Property.JUDDI_MAX_TMODELS_PER_PUBLISHER, -1);
131                 MaxBusinesses = AppConfig.getConfiguration().getInt(Property.JUDDI_MAX_BUSINESSES_PER_PUBLISHER, -1);
132         } catch (Exception ex) {
133                 MaxBindingsPerService = -1;
134                 MaxServicesPerBusiness = -1;
135                 MaxTmodels = -1;
136                 MaxBusinesses = -1;
137                 logger.error("config exception! " + authorizedName, ex);
138         }
139         boolean isLdapUser = false;
140         try {
141             env = new Hashtable<String, String>();
142             env.put(Context.INITIAL_CONTEXT_FACTORY, AppConfig.getConfiguration().getString(Property.JUDDI_AUTHENTICATOR_INITIAL_CONTEXT, "com.sun.jndi.ldap.LdapCtxFactory"));
143             env.put(Context.SECURITY_AUTHENTICATION, AppConfig.getConfiguration().getString(Property.JUDDI_AUTHENTICATOR_STYLE, "simple"));
144             env.put(Context.PROVIDER_URL, url); // organization ldap url, example ldap://localhost:389
145             env.put(Context.SECURITY_PRINCIPAL, authorizedName);
146             env.put(Context.SECURITY_CREDENTIALS, cred);
147             ctx = new InitialLdapContext(env, null);
148             isLdapUser = true;
149             logger.info(authorizedName + " is authenticated");
150            
151         } catch (ConfigurationException e) {
152             logger.error(authorizedName + " is not authenticated", e);
153             throw new UnknownUserException(new ErrorMessage("errors.auth.NoPublisher", authorizedName));
154         }
155         catch (NamingException e) {
156             logger.error(authorizedName + " is not authenticated");
157             throw new UnknownUserException(new ErrorMessage("errors.auth.NoPublisher", authorizedName));
158         }finally {
159             try {
160                 ctx.close();
161             } catch (NamingException e) {
162                 logger.error("Context close failure " + e);
163             }
164         }
165 
166         if (isLdapUser) {
167             EntityManager em = PersistenceManager.getEntityManager();
168             EntityTransaction tx = em.getTransaction();
169             try {
170                 tx.begin();
171                 Publisher publisher = em.find(Publisher.class, authorizedName);
172                 if (publisher == null) {
173                     logger.warn("Publisher was not found in the database, adding the publisher in on the fly.");
174                     publisher = new Publisher();
175                     publisher.setAuthorizedName(authorizedName);
176                     publisher.setIsAdmin("false");
177                     publisher.setIsEnabled("true");
178                     publisher.setMaxBindingsPerService(MaxBindingsPerService);
179                     publisher.setMaxBusinesses(MaxBusinesses);
180                     publisher.setMaxServicesPerBusiness(MaxServicesPerBusiness);
181                     publisher.setMaxTmodels(MaxTmodels);
182                     publisher.setPublisherName("Unknown");
183                     em.persist(publisher);
184                     tx.commit();
185                 }
186             } finally {
187                 if (tx.isActive()) {
188                     tx.rollback();
189                 }
190                 em.close();
191             }
192         } else {
193             throw new UnknownUserException(new ErrorMessage("errors.auth.NoPublisher", authorizedName));
194         }
195         return authorizedName;
196     }
197 
198     public UddiEntityPublisher identify(String authInfo, String authorizedName, WebServiceContext ctx) throws AuthenticationException, FatalErrorException {
199         EntityManager em = PersistenceManager.getEntityManager();
200         EntityTransaction tx = em.getTransaction();
201         try {
202             tx.begin();
203             Publisher publisher = em.find(Publisher.class, authorizedName);
204             if (publisher == null)
205                 throw new UnknownUserException(new ErrorMessage("errors.auth.NoPublisher", authorizedName));
206             return publisher;
207         } finally {
208             if (tx.isActive()) {
209                 tx.rollback();
210             }
211             em.close();
212         }
213     }
214 }