/** * Copyright (c) 2009 Juwi MacMillan Group GmbH * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package de.juwimm.cms.authorization.jaas; import java.security.Principal; import java.security.acl.Group; import java.util.Enumeration; import java.util.Iterator; import java.util.Map; import java.util.Set; import javax.security.auth.Subject; import javax.security.auth.callback.CallbackHandler; import javax.security.auth.login.LoginException; import javax.security.auth.spi.LoginModule; import org.apache.log4j.Logger; /** * <p>Title: ConQuest</p> * <p>Description: Enterprise Content Management</p> * <p>Copyright: Copyright (c) 2003</p> * <p>Company: JuwiMacMillan Group</p> * @author <a href="s.kulawik@juwimm.com">Sascha-Matthias Kulawik</a> * @author <a href="mailto:carsten.schalm@juwimm.com">Carsten Schalm</a> * , Juwi|MacMillan Group Gmbh, Walsrode, Germany * @version $Id$ */ public class DatabaseServerLoginModule implements LoginModule { private static final Logger log = Logger.getLogger(DatabaseServerLoginModule.class); protected Subject subject; protected CallbackHandler callbackHandler; protected Principal identity; private String dsJndiName; /** * Initialize the login module. This stores the subject, callbackHandler * and sharedState and options for the login session. Subclasses should override * if they need to process their own options. A call to super.initialize(...) * must be made in the case of an override. * * @param subject the Subject to update after a successful login. * @param callbackHandler the CallbackHandler that will be used to obtain the * the user identity and credentials. * @param sharedState a Map shared between all configured login module instances * @param options the parameters passed to the login module. */ public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, Map options) { if (log.isTraceEnabled()) { log.trace("initialize"); } this.subject = subject; this.callbackHandler = callbackHandler; Object username = sharedState.get("javax.security.auth.login.name"); if (username instanceof Principal) { if (log.isTraceEnabled()) { log.trace("found principal object"); } this.identity = (Principal) username; } else { if (log.isTraceEnabled()) { log.trace("creating principal object"); } String name = username.toString(); this.identity = new SimplePrincipal(name); } this.dsJndiName = (String) options.get("dsJndiName"); if (this.dsJndiName == null) { this.dsJndiName = "java:/ConQuestDS"; } if (log.isTraceEnabled()) { log.trace("login " + this.identity.getName()); log.trace("initialize, instance=@" + System.identityHashCode(this)); } } /** Perform the authentication of the username and password. */ public boolean login() throws LoginException { if (log.isTraceEnabled()) { log.trace("login"); } return true; } /** Method to commit the authentication process (phase 2). If the login method completed successfully as indicated by loginOk == true, this method adds the getIdentity() value to the subject getPrincipals() Set. It also adds the members of each Group returned by getRoleSets() to the subject getPrincipals() Set. @see javax.security.auth.Subject @see java.security.acl.Group @return true always. */ public boolean commit() throws LoginException { if (log.isTraceEnabled()) { log.trace("commit"); } Set principals = this.subject.getPrincipals(); principals.add(this.identity); Group[] roleSets = this.getRoleSets(); for (int g = 0; g < roleSets.length; g++) { Group group = roleSets[g]; String name = group.getName(); Group subjectGroup = this.createGroup(name, principals); Enumeration members = group.members(); while (members.hasMoreElements()) { Principal role = (Principal) members.nextElement(); try { subjectGroup.addMember(role); } catch (IllegalArgumentException e) { SimpleGroup tmp = new SimpleGroup("Roles"); subjectGroup.addMember(tmp); subjectGroup = tmp; subjectGroup.addMember(role); } } } return true; } private Group[] getRoleSets() { return DatabaseAuthorization.getRoleSets(this.dsJndiName, this.identity.getName()); } /** Method to abort the authentication process (phase 2). @return true alaways */ public boolean abort() throws LoginException { if (log.isTraceEnabled()) { log.trace("abort"); } return true; } /** Remove the user identity and roles added to the Subject during commit. @return true always. */ public boolean logout() throws LoginException { if (log.isTraceEnabled()) log.trace("logout"); // Remove the user identity Set principals = this.subject.getPrincipals(); principals.remove(this.identity); // Remove any added Groups... return true; } /** Find or create a Group with the given name. Subclasses should use this method to locate the 'Roles' group or create additional types of groups. @return A named Group from the principals set. */ private Group createGroup(String name, Set principals) { Group roles = null; Iterator iter = principals.iterator(); while (iter.hasNext()) { Object next = iter.next(); if (!(next instanceof Group)) { continue; } Group grp = (Group) next; if (grp.getName().equals(name)) { roles = grp; break; } } // If we did not find a group create one if (roles == null) { roles = new SimpleGroup(name); principals.add(roles); } return roles; } }