Index: topia-service/src/java/org/codelutin/topia/taas/jaas/TaasPermission.java diff -u /dev/null topia-service/src/java/org/codelutin/topia/taas/jaas/TaasPermission.java:1.1 --- /dev/null Thu Nov 29 16:08:34 2007 +++ topia-service/src/java/org/codelutin/topia/taas/jaas/TaasPermission.java Thu Nov 29 16:08:29 2007 @@ -0,0 +1,107 @@ +/* *##% +* 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: 2007-11-29 16:08:29 $ +* par : $Author: ruchaud $ +*/ + +package org.codelutin.topia.taas.jaas; + +import java.security.Permission; + +import org.codelutin.topia.taas.TaasAuthorization; +import org.codelutin.topia.taas.TaasUtil; + +/** + * Classe permettant d'encapsuler les autorisations et de déléguer le travail aux + * autorisations. + * @author ruchaud + */ +public class TaasPermission extends Permission { + + private static final long serialVersionUID = 1L; + + private TaasAuthorization authorization; + + public TaasPermission(TaasAuthorization authorization) { + super(authorization.getExpression()); + this.authorization = authorization; + } + + /* + * (non-Javadoc) + * @see java.security.Permission#implies(java.security.Permission) + */ + @Override + public boolean implies(Permission permission) { + if (permission == null) + return false; + if (!(permission instanceof TaasPermission)) + return false; + TaasPermission other = (TaasPermission)permission; + return authorization.implies(other.getAuthorization()); + } + + /* + * (non-Javadoc) + * @see java.security.Permission#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) { + if (obj == null) + return false; + if (obj == this) + return true; + if (!(obj instanceof TaasPermission)) + return false; + TaasPermission that = (TaasPermission)obj; + return (this.implies(that) && that.implies(this)); + } + + /* + * (non-Javadoc) + * @see java.security.Permission#hashCode() + */ + @Override + public int hashCode() { + return authorization.hashCode(); + } + + /* + * (non-Javadoc) + * @see java.security.Permission#getActions() + */ + @Override + public String getActions() { + return TaasUtil.actionsInt2String(authorization.getActions()); + } + + public TaasAuthorization getAuthorization() { + return authorization; + } +} Index: topia-service/src/java/org/codelutin/topia/taas/jaas/TaasPrincipalWrapper.java diff -u /dev/null topia-service/src/java/org/codelutin/topia/taas/jaas/TaasPrincipalWrapper.java:1.1 --- /dev/null Thu Nov 29 16:08:34 2007 +++ topia-service/src/java/org/codelutin/topia/taas/jaas/TaasPrincipalWrapper.java Thu Nov 29 16:08:29 2007 @@ -0,0 +1,79 @@ +/* *##% +* 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: 2007-11-29 16:08:29 $ +* par : $Author: ruchaud $ +*/ + +package org.codelutin.topia.taas.jaas; + +import java.security.Principal; + +/** + * Implantation des principals de JAAS. + * @author ruchaud + */ +public class TaasPrincipalWrapper implements Principal { + + protected String name; + + /** + * Contructeur avec comme paramètre le nom du principal. + * @param name topiaId d'un group ou d'utilisateur + */ + public TaasPrincipalWrapper(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 TaasPrincipalWrapper)) + return false; + if (name == null) { + return (((Principal)o).getName() == null); + } + return name.equals(((TaasPrincipalWrapper)o).getName()); + } + +} //TopiaPrincipal Index: topia-service/src/java/org/codelutin/topia/taas/jaas/TaasPolicy.java diff -u /dev/null topia-service/src/java/org/codelutin/topia/taas/jaas/TaasPolicy.java:1.1 --- /dev/null Thu Nov 29 16:08:34 2007 +++ topia-service/src/java/org/codelutin/topia/taas/jaas/TaasPolicy.java Thu Nov 29 16:08:29 2007 @@ -0,0 +1,177 @@ +/* *##% + * 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: 2007-11-29 16:08:29 $ + * par : $Author: ruchaud $ + */ + +package org.codelutin.topia.taas.jaas; + +import java.security.AccessController; +import java.security.CodeSource; +import java.security.Permission; +import java.security.PermissionCollection; +import java.security.Policy; +import java.security.Principal; +import java.security.ProtectionDomain; + +import javax.security.auth.Subject; + +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.TopiaServiceDAOHelper; +import org.codelutin.topia.taas.TaasAuthorization; +import org.codelutin.topia.taas.TaasPrincipal; +import org.codelutin.topia.taas.TaasPrincipalDAO; +import org.codelutin.topia.taas.TaasService; + +/** + * Implantation d'un policy avec une prise en compte des permissions à la volée. + * @author ruchaud + */ +public class TaasPolicy extends Policy { + + private Log log = LogFactory.getLog(TaasPolicy.class); + + protected Policy parentPolicy; + + protected TaasService taasService; + + public TaasPolicy(TaasService taasService) { + this.taasService = taasService; + } + + /** + * 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); + + Subject subject = Subject.getSubject(AccessController.getContext()); + if (subject != null) { + for (Principal principal : subject.getPrincipals()) { + try { + String principalName = principal.getName(); + + TopiaContext rootContext = taasService.getRootContext(); + TopiaContext transaction = rootContext.beginTransaction(); + + TaasPrincipalDAO principalDAO = TopiaServiceDAOHelper.getTaasPrincipalDAO(transaction); + TaasPrincipal taasPrincipal = principalDAO.findByName(principalName); + + for (TaasAuthorization authorization : taasPrincipal.getAuthorizations()) { + TaasPermission permission = new TaasPermission(authorization); + pc.add(permission); + } + + transaction.closeContext(); + } catch (TopiaException e) { + log.error("Récupération des TopiaPermission impossible", e); + } + } + } else { + log.error("Récupération des TopiaPermission impossible"); + } + + 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 TaasPolicy) { + 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-service/src/java/org/codelutin/topia/taas/jaas/TaasLoginModule.java diff -u /dev/null topia-service/src/java/org/codelutin/topia/taas/jaas/TaasLoginModule.java:1.1 --- /dev/null Thu Nov 29 16:08:34 2007 +++ topia-service/src/java/org/codelutin/topia/taas/jaas/TaasLoginModule.java Thu Nov 29 16:08:29 2007 @@ -0,0 +1,196 @@ +/* *##% +* 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: 2007-11-29 16:08:29 $ +* par : $Author: ruchaud $ +*/ + +package org.codelutin.topia.taas.jaas; + + +import java.security.Principal; +import java.util.Collection; +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.TopiaContext; +import org.codelutin.topia.TopiaException; +import org.codelutin.topia.TopiaServiceDAOHelper; +import org.codelutin.topia.taas.TaasPrincipal; +import org.codelutin.topia.taas.TaasService; +import org.codelutin.topia.taas.TaasUser; +import org.codelutin.topia.taas.TaasUserDAO; +import org.codelutin.topia.taas.TaasUtil; + +/** + * LoginModule permettant l'authentification d'un utilisateur au près du système. + * @author ruchaud + */ +public class TaasLoginModule implements LoginModule { + + private Log log = LogFactory.getLog(TaasLoginModule.class); + + private Subject subject; + private CallbackHandler callbackHandler; + private Set principals; + private TaasService taasService; + + /* (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.taasService = (TaasService)options.get(TaasService.CONF_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 (taasService == null) { + throw new LoginException("TaasService 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(); + + String hashed = TaasUtil.hash(password); + + //Vérification du login/pass et récupération des Principals + try { + TopiaContext rootContext = taasService.getRootContext(); + TopiaContext transaction = rootContext.beginTransaction(); + + TaasUserDAO userDAO = TopiaServiceDAOHelper.getTaasUserDAO(transaction); + TaasUser user = userDAO.findByLogin(login); + + if(user != null && user.getPassword().equals(hashed)) { + // Récupération des principals + principals = new HashSet(); + + principals.add(new TaasPrincipalWrapper(user.getLogin())); + + Collection taasPrincipals = user.getPrincipals(); + for (TaasPrincipal taasPrincipal : taasPrincipals) { + principals.add(new TaasPrincipalWrapper(taasPrincipal.getName())); + } + + } else { + // Echec d'authentification + principals = null; + throw new LoginException("Erreur lors de l'authentification " + login); + } + + transaction.closeContext(); + } 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; + } + + return true; + } + + /* (non-Javadoc) + * @see javax.security.auth.spi.LoginModule#commit() + */ + public boolean commit() throws LoginException { + 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().removeAll(principals); + subject = null; + principals.clear(); + principals = null; + callbackHandler = null; + return true; + } + +} //TopiaLoginModule Index: topia-service/src/java/org/codelutin/topia/taas/jaas/TaasConfiguration.java diff -u /dev/null topia-service/src/java/org/codelutin/topia/taas/jaas/TaasConfiguration.java:1.1 --- /dev/null Thu Nov 29 16:08:34 2007 +++ topia-service/src/java/org/codelutin/topia/taas/jaas/TaasConfiguration.java Thu Nov 29 16:08:29 2007 @@ -0,0 +1,154 @@ +/* *##% + * 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: 2007-11-29 16:08:29 $ + * par : $Author: ruchaud $ + */ + +package org.codelutin.topia.taas.jaas; + +import java.util.HashMap; +import java.util.Map; + +import javax.security.auth.login.AppConfigurationEntry; +import javax.security.auth.login.Configuration; + +import org.codelutin.topia.taas.TaasService; + +/** + * Classe permettant de passer des paramètres entre le LoginModule et le + * CallbackHandler. Ici on passe le SecurityManager. + * @author ruchaud + */ +public class TaasConfiguration 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 taasService le service + */ + public TaasConfiguration(String name, TaasService taasService) { + super(); + appConfEntries = new HashMap(); + addEntry(name, taasService); + } + + /** + * 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, TaasService taasService) { + AppConfigurationEntry[] confEntries = getAppConfigurationEntry(name); + if (confEntries != null) { + int i = 0; + for (; i < confEntries.length; i++) + if (TaasService.CONF_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(taasService); + } else { + if ( /* Mauvais FLAG */ + !AppConfigurationEntry.LoginModuleControlFlag.REQUIRED + .equals(confEntries[i].getControlFlag()) + /* Ne contient pas la propriété */ + || !confEntries[i].getOptions().containsKey( + TaasService.CONF_KEY) + /* Propriété mal initialisée */ + || !confEntries[i].getOptions() + .get(TaasService.CONF_KEY).equals(taasService)) + confEntries[i] = createEntry(taasService, confEntries[i] + .getOptions()); + } + } else { + confEntries = new AppConfigurationEntry[1]; + confEntries[0] = createEntry(taasService); + } + appConfEntries.put(name, confEntries); + } + + /** + * Créé une entry avec des options vides + * + * @param securityHelper + * le SecurityHelper + * @return l'entry créée + */ + private AppConfigurationEntry createEntry(TaasService taasService) { + return createEntry(taasService, 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(TaasService taasService, Map options) { + if (options == null) + options = new HashMap(); + options.put(TaasService.CONF_KEY, taasService); + return new AppConfigurationEntry(TaasService.CONF_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