Index: topia-security/src/java/org/codelutin/topia/security/jaas/TopiaPrincipal.java diff -u /dev/null topia-security/src/java/org/codelutin/topia/security/jaas/TopiaPrincipal.java:1.1 --- /dev/null Wed Sep 13 08:45:15 2006 +++ topia-security/src/java/org/codelutin/topia/security/jaas/TopiaPrincipal.java Wed Sep 13 08:45:10 2006 @@ -0,0 +1,71 @@ +/* *##% +* Copyright (C) 2002, 2003, 2004, 2005 Code Lutin, +* Cédric Pineau, Benjamin Poussin, +* +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*##%*/ + +/* * +* TopiaPrincipal.java +* +* Created: 15 févr. 2006 +* +* @author Arnaud Thimel +* @version $Revision: 1.1 $ +* +* Mise a jour: $Date: 2006/09/13 08:45:10 $ +* par : $Author: ruchaud $ +*/ + +package org.codelutin.topia.security.jaas; + +import java.security.Principal; + +public class TopiaPrincipal implements Principal { + + protected String name; + + public TopiaPrincipal(String name) { + this.name = name; + } + + /* (non-Javadoc) + * @see java.security.Principal#getName() + */ + public String getName() { + return name; + } + + /* (non-Javadoc) + * @see java.lang.Object#toString() + */ + public String toString() { + return this.getClass().getName() + " : " + name; + } + + /* (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + public boolean equals(Object o) { + if (!(o instanceof TopiaPrincipal)) + return false; + if (name == null) { + return (((Principal)o).getName() == null); + } + return name.equals(((TopiaPrincipal)o).getName()); + } + +} //TopiaPrincipal Index: topia-security/src/java/org/codelutin/topia/security/jaas/TopiaPolicy.java diff -u /dev/null topia-security/src/java/org/codelutin/topia/security/jaas/TopiaPolicy.java:1.1 --- /dev/null Wed Sep 13 08:45:15 2006 +++ topia-security/src/java/org/codelutin/topia/security/jaas/TopiaPolicy.java Wed Sep 13 08:45:10 2006 @@ -0,0 +1,165 @@ +/* *##% + * Copyright (C) 2002, 2003, 2004, 2005 Code Lutin, + * Cédric Pineau, Benjamin Poussin, + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + *##%*/ + +/* * + * TopiaPolicy.java + * + * Created: 17 févr. 2006 + * + * @author Arnaud Thimel + * @version $Revision: 1.1 $ + * + * Mise a jour: $Date: 2006/09/13 08:45:10 $ + * par : $Author: ruchaud $ + */ + +package org.codelutin.topia.security.jaas; + +import java.security.CodeSource; +import java.security.Permission; +import java.security.PermissionCollection; +import java.security.Policy; +import java.security.ProtectionDomain; +import java.util.Collection; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.codelutin.topia.TopiaContext; +import org.codelutin.topia.TopiaException; +import org.codelutin.topia.framework.TopiaContextImplementor; +import org.codelutin.topia.security.TopiaSecurityDAOHelper; +import org.codelutin.topia.security.entities.authorization.TopiaAuthorization; +import org.codelutin.topia.security.entities.authorization.TopiaAuthorizationDAO; + + +public class TopiaPolicy extends Policy { + + private Log log = LogFactory.getLog(TopiaPolicy.class); + + private TopiaContextImplementor topiaContext; + + protected Policy parentPolicy; + + public TopiaPolicy(TopiaContext context) { + super(); + this.topiaContext = (TopiaContextImplementor) context; + } + + private TopiaAuthorizationDAO getTopiaAuthorizationDAO() { + try { + return TopiaSecurityDAOHelper.getTopiaAuthorizationDAO(topiaContext.beginTransaction()); + } catch (TopiaException te) { + log.error("Permission manager non accessible", te); + } + return null; + } + + /** + * Renvoie la Policy parente + * @see #installPolicy() + * @return l'attribut parentPolicy + */ + public Policy getParentPolicy() { + return parentPolicy; + } + + /** + * Remplace la Policy parente + * @param parentPolicy + * la nouvelle Policy parente + */ + public void setParentPolicy(Policy parentPolicy) { + this.parentPolicy = parentPolicy; + } + + /* (non-Javadoc) + * @see java.security.Policy#getPermissions(java.security.CodeSource) + */ + @Override + public PermissionCollection getPermissions(CodeSource codesource) { + PermissionCollection pc = parentPolicy.getPermissions(codesource); + return pc; + } + + /* (non-Javadoc) + * @see java.security.Policy#getPermissions(java.security.ProtectionDomain) + */ + @Override + public PermissionCollection getPermissions(ProtectionDomain domain) { + PermissionCollection pc = parentPolicy.getPermissions(domain); + TopiaAuthorizationDAO authorizationDAO = getTopiaAuthorizationDAO(); + if (authorizationDAO != null) { + try { + Collection authorizations = authorizationDAO.findAll(); + for (TopiaAuthorization authorization : authorizations) { + pc.add(new TopiaPermission(authorization)); + } + } catch (TopiaException te) { + log.error("Récupération des TopiaPermission impossible", te); + } + } + return pc; + } + + /* (non-Javadoc) + * @see java.security.Policy#refresh() + */ + @Override + public void refresh() { + parentPolicy.refresh(); + } + + /* (non-Javadoc) + * @see java.security.Policy#implies(java.security.ProtectionDomain, + * java.security.Permission) + */ + @Override + public boolean implies(ProtectionDomain domain, Permission permission) { + PermissionCollection pc = getPermissions(domain); + if (pc == null) { + return false; + } + return pc.implies(permission); + } + + /** + * Installe cette TopiaPolicy. Si la Policy existante est déja cette + * TopiaPolicy alors la méthode n'a pas d'effet. Si une autre Policy existe + * deja alors cette TopiaPolicy, elle conserve l'ancienne Policy dans + * parentPolicy et la remplace alors. + */ + public void installPolicy() { + Policy policy = Policy.getPolicy(); + if (policy == this) + return; + if (policy instanceof TopiaPolicy) { + if (log.isDebugEnabled()) { + log.debug("Policy deja modifie en: " + policy); + } + } else { + if (log.isDebugEnabled()) { + log.debug("l'ancienne Policy etait: " + policy); + } + setParentPolicy(policy); + Policy.setPolicy(this); + } + } + +} // TopiaPolicy Index: topia-security/src/java/org/codelutin/topia/security/jaas/TopiaConfiguration.java diff -u /dev/null topia-security/src/java/org/codelutin/topia/security/jaas/TopiaConfiguration.java:1.1 --- /dev/null Wed Sep 13 08:45:15 2006 +++ topia-security/src/java/org/codelutin/topia/security/jaas/TopiaConfiguration.java Wed Sep 13 08:45:10 2006 @@ -0,0 +1,153 @@ +/* *##% + * Copyright (C) 2002, 2003, 2004, 2005 Code Lutin, + * Cédric Pineau, Benjamin Poussin, + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + *##%*/ + +/* * + * TopiaConfiguration.java + * + * Created: 20 févr. 2006 + * + * @author Arnaud Thimel + * @version $Revision: 1.1 $ + * + * Mise a jour: $Date: 2006/09/13 08:45:10 $ + * par : $Author: ruchaud $ + */ + +package org.codelutin.topia.security.jaas; + +import static org.codelutin.topia.security.TopiaSecurityUtil.SECURITY_MANAGER_KEY; +import static org.codelutin.topia.security.TopiaSecurityUtil.TOPIA_LOGIN_MODULE; + +import java.util.HashMap; +import java.util.Map; + +import javax.security.auth.login.AppConfigurationEntry; +import javax.security.auth.login.Configuration; + +import org.codelutin.topia.security.TopiaSecurityManager; + +public class TopiaConfiguration extends Configuration { + + private Map appConfEntries; + + /** + * Créé une instance de TopiConfiguration avec un identifiant de + * configurationEntry et le nom du fichier de propriétés associé. + * + * @param name + * le nom de la configurationEntry + * @param securityManagerPropertiesName + * le nom du fichier de propriétés + */ + public TopiaConfiguration(String name, TopiaSecurityManager securityManager) { + super(); + appConfEntries = new HashMap(); + addEntry(name, securityManager); + } + + /** + * Ajoute une ConfigurationEntry avec le nom de fichier de propriétés + * associé + * + * @param name + * le nom de la configurationEntry + * @param securityHelper + * le nom du fichier de propriétés + */ + private void addEntry(String name, TopiaSecurityManager securityManager) { + AppConfigurationEntry[] confEntries = getAppConfigurationEntry(name); + if (confEntries != null) { + int i = 0; + for (; i < confEntries.length; i++) + if (TOPIA_LOGIN_MODULE.equals(confEntries[i] + .getLoginModuleName())) + break; + if (i == confEntries.length) { + AppConfigurationEntry[] tmpConfEntries = confEntries; + confEntries = new AppConfigurationEntry[confEntries.length + 1]; + for (int j = 0; j < confEntries.length; j++) + confEntries[j] = tmpConfEntries[j]; + confEntries[confEntries.length - 1] = createEntry(securityManager); + } else { + if ( /* Mauvais FLAG */ + !AppConfigurationEntry.LoginModuleControlFlag.REQUIRED + .equals(confEntries[i].getControlFlag()) + /* Ne contient pas la propriété */ + || !confEntries[i].getOptions().containsKey( + SECURITY_MANAGER_KEY) + /* Propriété mal initialisée */ + || !confEntries[i].getOptions() + .get(SECURITY_MANAGER_KEY).equals(securityManager)) + confEntries[i] = createEntry(securityManager, confEntries[i] + .getOptions()); + } + } else { + confEntries = new AppConfigurationEntry[1]; + confEntries[0] = createEntry(securityManager); + } + appConfEntries.put(name, confEntries); + } + + /** + * Créé une entry avec des options vides + * + * @param securityHelper + * le SecurityHelper + * @return l'entry créée + */ + private AppConfigurationEntry createEntry(TopiaSecurityManager securityManager) { + return createEntry(securityManager, null); + } + + /** + * Créé une entry en rajoutant les options nécessaires à l'attribut options + * + * @param securityHelper + * le nom du fichier de propriétés + * @param options + * l'objet contenant les options précédentes + * @return l'entry créée + */ + private AppConfigurationEntry createEntry(TopiaSecurityManager securityManager, Map options) { + if (options == null) + options = new HashMap(); + options.put(SECURITY_MANAGER_KEY, securityManager); + return new AppConfigurationEntry(TOPIA_LOGIN_MODULE, + AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, options); + } + + /** + * Renvoie les entries associéess à l'attribut name + * + * @param name + * l'identifiant des entries demandées + * @return un tableau cotenant les entries demandées + */ + public AppConfigurationEntry[] getAppConfigurationEntry(String name) { + return appConfEntries.get(name); + } + + /* (non-Javadoc) + * @see javax.security.auth.login.Configuration#refresh() + */ + public void refresh() { + } + +} // TopiaConfiguration Index: topia-security/src/java/org/codelutin/topia/security/jaas/TopiaPermission.java diff -u /dev/null topia-security/src/java/org/codelutin/topia/security/jaas/TopiaPermission.java:1.1 --- /dev/null Wed Sep 13 08:45:17 2006 +++ topia-security/src/java/org/codelutin/topia/security/jaas/TopiaPermission.java Wed Sep 13 08:45:10 2006 @@ -0,0 +1,86 @@ +/* *##% +* Copyright (C) 2002, 2003, 2004, 2005 Code Lutin, +* Cédric Pineau, Benjamin Poussin, +* +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*##%*/ + +/* * +* TopiaPermission.java +* +* Created: 16 févr. 2006 +* +* @author Arnaud Thimel +* @version $Revision: 1.1 $ +* +* Mise a jour: $Date: 2006/09/13 08:45:10 $ +* par : $Author: ruchaud $ +*/ + + +package org.codelutin.topia.security.jaas; + +import java.security.Permission; + +import org.codelutin.topia.security.entities.authorization.TopiaAuthorization; + +public class TopiaPermission extends Permission { + + private static final long serialVersionUID = 1L; + + private TopiaAuthorization authorization; + + public TopiaPermission(TopiaAuthorization authorization) { + super(authorization.getId()); + this.authorization = authorization; + } + + @Override + public boolean implies(Permission permission) { + if (permission == null) + return false; + if (!(permission instanceof TopiaPermission)) + return false; + TopiaPermission other = (TopiaPermission)permission; + return authorization.implies(other.getAuthorization()); + } + + @Override + public boolean equals(Object obj) { + if (obj == null) + return false; + if (obj == this) + return true; + if (!(obj instanceof TopiaPermission)) + return false; + TopiaPermission that = (TopiaPermission)obj; + return (this.implies(that) && that.implies(this)); + } + + @Override + public int hashCode() { + return authorization.hashCode(); + } + + @Override + public String getActions() { + return authorization.getActionsAsString(); + } + + public TopiaAuthorization getAuthorization() { + return authorization; + } +} Index: topia-security/src/java/org/codelutin/topia/security/jaas/TopiaCallbackHandler.java diff -u /dev/null topia-security/src/java/org/codelutin/topia/security/jaas/TopiaCallbackHandler.java:1.1 --- /dev/null Wed Sep 13 08:45:17 2006 +++ topia-security/src/java/org/codelutin/topia/security/jaas/TopiaCallbackHandler.java Wed Sep 13 08:45:10 2006 @@ -0,0 +1,78 @@ +/* *##% + * Copyright (C) 2002, 2003, 2004, 2005 Code Lutin, + * Cédric Pineau, Benjamin Poussin, + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + *##%*/ + +/* * + * TopiaCallbackHandler.java + * + * Created: 20 févr. 2006 + * + * @author Arnaud Thimel + * @version $Revision: 1.1 $ + * + * Mise a jour: $Date: 2006/09/13 08:45:10 $ + * par : $Author: ruchaud $ + */ + +package org.codelutin.topia.security.jaas; + +import java.io.IOException; + +import javax.security.auth.callback.Callback; +import javax.security.auth.callback.CallbackHandler; +import javax.security.auth.callback.NameCallback; +import javax.security.auth.callback.PasswordCallback; +import javax.security.auth.callback.UnsupportedCallbackException; + +public class TopiaCallbackHandler implements CallbackHandler { + + private String username; + + private String password; + + /** + * @param username + * @param password + */ + public TopiaCallbackHandler(String username, String password) { + super(); + this.username = username; + this.password = password; + } + + /* + * (non-Javadoc) + * + * @see javax.security.auth.callback.CallbackHandler#handle(javax.security.auth.callback.Callback[]) + */ + public void handle(Callback[] callbacks) throws IOException, + UnsupportedCallbackException { + for (int i = 0; i < callbacks.length; i++) { + if (callbacks[i] instanceof NameCallback) { + NameCallback nc = (NameCallback) callbacks[i]; + nc.setName(username); + } else if (callbacks[i] instanceof PasswordCallback) { + PasswordCallback pc = (PasswordCallback) callbacks[i]; + pc.setPassword(password.toCharArray()); + } else + throw new UnsupportedCallbackException(callbacks[i]); + } + } + +} Index: topia-security/src/java/org/codelutin/topia/security/jaas/TopiaLoginModule.java diff -u /dev/null topia-security/src/java/org/codelutin/topia/security/jaas/TopiaLoginModule.java:1.1 --- /dev/null Wed Sep 13 08:45:18 2006 +++ topia-security/src/java/org/codelutin/topia/security/jaas/TopiaLoginModule.java Wed Sep 13 08:45:10 2006 @@ -0,0 +1,188 @@ +/* *##% +* Copyright (C) 2002, 2003, 2004, 2005 Code Lutin, +* Cédric Pineau, Benjamin Poussin, +* +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*##%*/ + +/* * +* TopiaLoginModule.java +* +* Created: 15 févr. 2006 +* +* @author Arnaud Thimel +* @version $Revision: 1.1 $ +* +* Mise a jour: $Date: 2006/09/13 08:45:10 $ +* par : $Author: ruchaud $ +*/ + + +package org.codelutin.topia.security.jaas; + +import java.security.Principal; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import javax.security.auth.Subject; +import javax.security.auth.callback.Callback; +import javax.security.auth.callback.CallbackHandler; +import javax.security.auth.callback.NameCallback; +import javax.security.auth.callback.PasswordCallback; +import javax.security.auth.login.LoginException; +import javax.security.auth.spi.LoginModule; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.codelutin.topia.TopiaException; +import org.codelutin.topia.framework.TopiaContextImplementor; +import org.codelutin.topia.security.TopiaSecurityManager; +import org.codelutin.topia.security.entities.TopiaPrincipal; +import org.codelutin.topia.security.entities.user.TopiaGroup; +import org.codelutin.topia.security.entities.user.TopiaUser; +import org.codelutin.topia.security.entities.user.TopiaUserDAO; +import static org.codelutin.topia.security.TopiaSecurityUtil.hash; + +import static org.codelutin.topia.security.TopiaSecurityUtil.SECURITY_MANAGER_KEY; + +public class TopiaLoginModule extends Object implements LoginModule { + + private Log log = LogFactory.getLog(TopiaLoginModule.class); + + private Subject subject; + private CallbackHandler callbackHandler; + private boolean loginSuccess; + private Set principals; + private TopiaSecurityManager securityManager; + + /* (non-Javadoc) + * @see javax.security.auth.spi.LoginModule#initialize( + * javax.security.auth.Subject, + * javax.security.auth.callback.CallbackHandler, + * java.util.Map, + * java.util.Map) + */ + public void initialize(Subject subject, CallbackHandler callbackHandler, + Map sharedState, Map options) { + this.subject = subject; + this.callbackHandler = callbackHandler; + this.principals = null; + this.securityManager = (TopiaSecurityManager)options.get(SECURITY_MANAGER_KEY); + } + + /* (non-Javadoc) + * @see javax.security.auth.spi.LoginModule#login() + */ + public boolean login() throws LoginException { + if (callbackHandler == null) { + throw new LoginException("CallbackHandler cannot be null"); + } + if (securityManager == null) { + throw new LoginException("\"" + SECURITY_MANAGER_KEY + "\" property must be set"); + } + + String login, password = null; + + NameCallback nc = new NameCallback("login"); + PasswordCallback pc = new PasswordCallback("password", false); + + Callback[] callbacks = new Callback[2]; + + callbacks[0] = nc; + callbacks[1] = pc; + + try { + //Récupération du login et mot de passe + callbackHandler.handle(callbacks); + } catch (Exception eee) { + if (log.isWarnEnabled()) { + log.warn("Utilisation du CallbackHandler impossible", eee); + } + LoginException le = new LoginException( + "Utilisation du CallbackHandler impossible"); + le.initCause(eee); + throw le; + } + login = nc.getName(); + password = new String(pc.getPassword()); + pc.clearPassword(); + + //Véricfication du login/pass et récupération des Principal + TopiaUserDAO topiaUserDAO = securityManager.getTopiaUserDAO(); + TopiaUser user = null; + try { + user = topiaUserDAO.findByLogin(login); + } catch (TopiaException te) { + // Echec de récupération de l'utilisateur + if (log.isWarnEnabled()) { + log.warn("Erreur lors de l'authentification", te); + } + LoginException le = new LoginException( + "Erreur lors de l'authentification"); + le.initCause(te); + throw le; + } + + if(user != null && user.isCorrectPassword(hash(password))) { + // Récupération des principals + principals = new HashSet(); + principals.add(new TopiaPrincipal(user.getLogin())); + for(TopiaGroup group : user.getGroup()) { + principals.add(new TopiaPrincipal(group.getName())); + } + } else { + // Echec d'authentification + principals = null; + throw new LoginException("Erreur lors de l'authentification" + login); + } + + return true; + } + + /* (non-Javadoc) + * @see javax.security.auth.spi.LoginModule#commit() + */ + public boolean commit() throws LoginException { + if (loginSuccess) { + subject.getPrincipals().addAll(principals); + } + return true; + } + + /* (non-Javadoc) + * @see javax.security.auth.spi.LoginModule#abort() + */ + public boolean abort() throws LoginException { + //On effectue les mêmes actions que logout + return logout(); + } + + /* (non-Javadoc) + * @see javax.security.auth.spi.LoginModule#logout() + */ + public boolean logout() throws LoginException { + //On libère les ressources + subject.getPrincipals().remove(principals); + loginSuccess = false; + subject = null; + principals.clear(); + principals = null; + callbackHandler = null; + return true; + } + +} //TopiaLoginModule