2 * This document is a part of the source code and related artifacts
\r
3 * for CollectionSpace, an open source collections management system
\r
4 * for museums and related institutions:
\r
6 * http://www.collectionspace.org
\r
7 * http://wiki.collectionspace.org
\r
9 * Copyright 2009 University of California at Berkeley
\r
11 * Licensed under the Educational Community License (ECL), Version 2.0.
\r
12 * You may not use this file except in compliance with this License.
\r
14 * You may obtain a copy of the ECL 2.0 License at
\r
16 * https://source.collectionspace.org/collection-space/LICENSE.txt
\r
18 * Unless required by applicable law or agreed to in writing, software
\r
19 * distributed under the License is distributed on an "AS IS" BASIS,
\r
20 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
\r
21 * See the License for the specific language governing permissions and
\r
22 * limitations under the License.
\r
24 package org.collectionspace.authentication;
\r
26 import java.lang.reflect.Constructor;
\r
27 import java.security.Principal;
\r
28 import java.security.acl.Group;
\r
29 import java.sql.Connection;
\r
30 import java.sql.PreparedStatement;
\r
31 import java.sql.ResultSet;
\r
32 import java.sql.SQLException;
\r
34 import java.util.HashMap;
\r
35 import javax.naming.InitialContext;
\r
36 import javax.naming.NamingException;
\r
37 import javax.security.auth.login.FailedLoginException;
\r
38 import javax.security.auth.login.LoginException;
\r
39 import javax.sql.DataSource;
\r
40 import org.jboss.security.SimpleGroup;
\r
41 import org.jboss.security.SimplePrincipal;
\r
42 import org.jboss.security.auth.spi.DatabaseServerLoginModule;
\r
43 //import org.slf4j.Logger;
\r
44 //import org.slf4j.LoggerFactory;
\r
46 public class CSpaceDBLoginModule extends DatabaseServerLoginModule {
\r
48 //disabled due to classloading problem
\r
49 // private Logger logger = LoggerFactory.getLogger(CSpaceDBLoginModule.class);
\r
50 private boolean log = true; //logger.isDebugEnabled();
\r
52 private void log(String str) {
\r
53 System.out.println(str);
\r
56 protected String getUsersPassword() throws LoginException {
\r
58 String username = getUsername();
\r
59 String password = null;
\r
60 Connection conn = null;
\r
61 PreparedStatement ps = null;
\r
62 ResultSet rs = null;
\r
63 InitialContext ctx = null;
\r
66 ctx = new InitialContext();
\r
67 DataSource ds = (DataSource) ctx.lookup(dsJndiName);
\r
69 throw new IllegalArgumentException("datasource not found: " + dsJndiName);
\r
71 conn = ds.getConnection();
\r
74 log("Executing query: " + principalsQuery + ", with username: " + username);
\r
76 ps = conn.prepareStatement(principalsQuery);
\r
77 ps.setString(1, username);
\r
78 rs = ps.executeQuery();
\r
79 if (rs.next() == false) {
\r
81 log("Query returned no matches from db");
\r
83 throw new FailedLoginException("No matching username found");
\r
86 password = rs.getString(1);
\r
87 password = convertRawPassword(password);
\r
89 log("Obtained user password");
\r
91 } catch (NamingException ex) {
\r
92 LoginException le = new LoginException("Error looking up DataSource from: " + dsJndiName);
\r
95 } catch (SQLException ex) {
\r
96 LoginException le = new LoginException("Query failed");
\r
99 } catch (Exception ex) {
\r
100 LoginException le = new LoginException("Unknown Exception");
\r
107 } catch (SQLException e) {
\r
113 } catch (SQLException e) {
\r
116 if (conn != null) {
\r
119 } catch (SQLException ex) {
\r
125 } catch (Exception e) {
\r
132 /** Execute the rolesQuery against the dsJndiName to obtain the roles for
\r
133 the authenticated user.
\r
135 @return Group[] containing the sets of roles
\r
137 protected Group[] getRoleSets() throws LoginException {
\r
138 String username = getUsername();
\r
140 log("getRoleSets using rolesQuery: " + rolesQuery + ", username: " + username);
\r
143 Connection conn = null;
\r
144 HashMap setsMap = new HashMap();
\r
145 PreparedStatement ps = null;
\r
146 ResultSet rs = null;
\r
149 InitialContext ctx = new InitialContext();
\r
150 DataSource ds = (DataSource) ctx.lookup(dsJndiName);
\r
151 conn = ds.getConnection();
\r
152 // Get the user role names
\r
154 log("Executing query: " + rolesQuery + ", with username: " + username);
\r
157 ps = conn.prepareStatement(rolesQuery);
\r
159 ps.setString(1, username);
\r
160 } catch (ArrayIndexOutOfBoundsException ignore) {
\r
161 // The query may not have any parameters so just try it
\r
163 rs = ps.executeQuery();
\r
164 if (rs.next() == false) {
\r
166 log("No roles found");
\r
168 // if(aslm.getUnauthenticatedIdentity() == null){
\r
169 // throw new FailedLoginException("No matching username found in Roles");
\r
171 /* We are running with an unauthenticatedIdentity so create an
\r
172 empty Roles set and return.
\r
175 Group[] roleSets = {new SimpleGroup("Roles")};
\r
180 String name = rs.getString(1);
\r
181 String groupName = rs.getString(2);
\r
182 if (groupName == null || groupName.length() == 0) {
\r
183 groupName = "Roles";
\r
186 Group group = (Group) setsMap.get(groupName);
\r
187 if (group == null) {
\r
188 group = new SimpleGroup(groupName);
\r
189 setsMap.put(groupName, group);
\r
193 // Principal p = aslm.createIdentity(name);
\r
194 Principal p = createIdentity(name);
\r
196 log("Assign user to role " + name);
\r
199 group.addMember(p);
\r
200 } catch (Exception e) {
\r
201 log("Failed to create principal: " + name + " " + e.toString());
\r
204 } while (rs.next());
\r
205 } catch (NamingException ex) {
\r
206 LoginException le = new LoginException("Error looking up DataSource from: " + dsJndiName);
\r
209 } catch (SQLException ex) {
\r
210 LoginException le = new LoginException("Query failed");
\r
217 } catch (SQLException e) {
\r
223 } catch (SQLException e) {
\r
226 if (conn != null) {
\r
229 } catch (Exception ex) {
\r
235 Group[] roleSets = new Group[setsMap.size()];
\r
236 setsMap.values().toArray(roleSets);
\r
240 /** Utility method to create a Principal for the given username. This
\r
241 * creates an instance of the principalClassName type if this option was
\r
242 * specified using the class constructor matching: ctor(String). If
\r
243 * principalClassName was not specified, a SimplePrincipal is created.
\r
245 * @param username the name of the principal
\r
246 * @return the principal instance
\r
247 * @throws java.lang.Exception thrown if the custom principal type cannot be created.
\r
249 protected Principal createIdentity(String username)
\r
251 Principal p = null;
\r
252 if (principalClassName == null) {
\r
253 p = new SimplePrincipal(username);
\r
255 ClassLoader loader = Thread.currentThread().getContextClassLoader();
\r
256 Class clazz = loader.loadClass(principalClassName);
\r
257 Class[] ctorSig = {String.class};
\r
258 Constructor ctor = clazz.getConstructor(ctorSig);
\r
259 Object[] ctorArgs = {username};
\r
260 p = (Principal) ctor.newInstance(ctorArgs);
\r