diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/PasswordServlet.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/PasswordServlet.java index 5d07ea7147d9581fe140c98956454362652f750e..20fca463e31263da2908a76d88fff44da3cf668e 100644 --- a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/PasswordServlet.java +++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/PasswordServlet.java @@ -70,13 +70,19 @@ package ca.nrc.cadc.ac.server.web.users; import java.io.IOException; import java.security.AccessControlException; +import java.security.Principal; +import java.security.PrivilegedExceptionAction; import java.util.Set; +import java.util.TreeSet; import javax.security.auth.Subject; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import ca.nrc.cadc.ac.UserNotFoundException; +import ca.nrc.cadc.ac.server.ldap.LdapUserDAO; +import ca.nrc.cadc.net.TransientException; import org.apache.log4j.Logger; import ca.nrc.cadc.ac.User; @@ -85,6 +91,7 @@ import ca.nrc.cadc.auth.AuthenticationUtil; import ca.nrc.cadc.auth.HttpPrincipal; import ca.nrc.cadc.log.ServletLogInfo; import ca.nrc.cadc.util.StringUtil; +import org.omg.CORBA.UserException; /** @@ -117,37 +124,53 @@ public class PasswordServlet extends HttpServlet try { final Subject subject = AuthenticationUtil.getSubject(request); - if ((subject == null) - || (subject.getPrincipals(HttpPrincipal.class).isEmpty())) + if ((subject == null) || (subject.getPrincipals().isEmpty())) { logInfo.setMessage("Unauthorized subject"); response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); } else { - logInfo.setSubject(subject); - final Set<HttpPrincipal> webPrincipals = - subject.getPrincipals(HttpPrincipal.class); - final User<HttpPrincipal> user = - new User<HttpPrincipal>(webPrincipals.iterator().next()); - String oldPassword = request.getParameter("old_password"); - String newPassword = request.getParameter("new_password"); - if (StringUtil.hasText(oldPassword)) + Subject.doAs(subject, new PrivilegedExceptionAction<Object>() { - if (StringUtil.hasText(newPassword)) + public Object run() throws Exception { - (new LdapUserPersistence<HttpPrincipal>()) - .setPassword(user, oldPassword, newPassword); - } - else - { - throw new IllegalArgumentException("Missing new password"); + LdapUserPersistence<Principal> dao = new LdapUserPersistence<Principal>(); + User<Principal> user; + try + { + user = dao.getUser(subject.getPrincipals().iterator().next()); + } + catch (UserNotFoundException e) + { + throw new AccessControlException("User not found"); + } + + Subject logSubject = new Subject(false, user.getIdentities(), + new TreeSet(), new TreeSet()); + + logInfo.setSubject(logSubject); + + String oldPassword = request.getParameter("old_password"); + String newPassword = request.getParameter("new_password"); + if (StringUtil.hasText(oldPassword)) + { + if (StringUtil.hasText(newPassword)) + { + dao.setPassword(user, oldPassword, newPassword); + } + else + { + throw new IllegalArgumentException("Missing new password"); + } + } + else + { + throw new IllegalArgumentException("Missing old password"); + } + return null; } - } - else - { - throw new IllegalArgumentException("Missing old password"); - } + }); } } catch (IllegalArgumentException e) diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/auth/AuthenticatorImpl.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/auth/AuthenticatorImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..024549e6ea3053593c4734ac608638b875154193 --- /dev/null +++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/auth/AuthenticatorImpl.java @@ -0,0 +1,156 @@ +/* + ************************************************************************ + ******************* CANADIAN ASTRONOMY DATA CENTRE ******************* + ************** CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** + * + * (c) 2014. (c) 2014. + * Government of Canada Gouvernement du Canada + * National Research Council Conseil national de recherches + * Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 + * All rights reserved Tous droits réservés + * + * NRC disclaims any warranties, Le CNRC dénie toute garantie + * expressed, implied, or énoncée, implicite ou légale, + * statutory, of any kind with de quelque nature que ce + * respect to the software, soit, concernant le logiciel, + * including without limitation y compris sans restriction + * any warranty of merchantability toute garantie de valeur + * or fitness for a particular marchande ou de pertinence + * purpose. NRC shall not be pour un usage particulier. + * liable in any event for any Le CNRC ne pourra en aucun cas + * damages, whether direct or être tenu responsable de tout + * indirect, special or general, dommage, direct ou indirect, + * consequential or incidental, particulier ou général, + * arising from the use of the accessoire ou fortuit, résultant + * software. Neither the name de l'utilisation du logiciel. Ni + * of the National Research le nom du Conseil National de + * Council of Canada nor the Recherches du Canada ni les noms + * names of its contributors may de ses participants ne peuvent + * be used to endorse or promote être utilisés pour approuver ou + * products derived from this promouvoir les produits dérivés + * software without specific prior de ce logiciel sans autorisation + * written permission. préalable et particulière + * par écrit. + * + * This file is part of the Ce fichier fait partie du projet + * OpenCADC project. OpenCADC. + * + * OpenCADC is free software: OpenCADC est un logiciel libre ; + * you can redistribute it and/or vous pouvez le redistribuer ou le + * modify it under the terms of modifier suivant les termes de + * the GNU Affero General Public la “GNU Affero General Public + * License as published by the License” telle que publiée + * Free Software Foundation, par la Free Software Foundation + * either version 3 of the : soit la version 3 de cette + * License, or (at your option) licence, soit (à votre gré) + * any later version. toute version ultérieure. + * + * OpenCADC is distributed in the OpenCADC est distribué + * hope that it will be useful, dans l’espoir qu’il vous + * but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE + * without even the implied GARANTIE : sans même la garantie + * warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ + * or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF + * PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence + * General Public License for Générale Publique GNU Affero + * more details. pour plus de détails. + * + * You should have received Vous devriez avoir reçu une + * a copy of the GNU Affero copie de la Licence Générale + * General Public License along Publique GNU Affero avec + * with OpenCADC. If not, see OpenCADC ; si ce n’est + * <http://www.gnu.org/licenses/>. pas le cas, consultez : + * <http://www.gnu.org/licenses/>. + * + * $Revision: 4 $ + * + ************************************************************************ + */ + +package ca.nrc.cadc.auth; + +import ca.nrc.cadc.ac.User; +import ca.nrc.cadc.ac.UserNotFoundException; +import ca.nrc.cadc.ac.server.ldap.LdapUserPersistence; +import ca.nrc.cadc.profiler.Profiler; +import org.apache.log4j.Logger; + +import javax.security.auth.Subject; +import java.security.Principal; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; + +/** + * Implementation of default Authenticator for AuthenticationUtil in cadcUtil. + * This class augments the subject with additional identities using the + * access control library. + * + * @author pdowler + */ +public class AuthenticatorImpl implements Authenticator +{ + private static final Logger log = Logger.getLogger(AuthenticatorImpl.class); + + public AuthenticatorImpl() { } + + /** + * @param subject + * @return the possibly modified subject + */ + public Subject getSubject(Subject subject) + { + AuthMethod am = AuthenticationUtil.getAuthMethod(subject); + if (am == null || AuthMethod.ANON.equals(am)) + return subject; + + if (subject != null && subject.getPrincipals().size() > 0) + { + Profiler prof = new Profiler(AuthenticatorImpl.class); + this.augmentSubject(subject); + prof.checkpoint("userDAO.augmentSubject()"); + + // if the caller had an invalid or forged CADC_SSO cookie, we could get + // in here and then not match any known identity: drop to anon + if ( subject.getPrincipals(HttpPrincipal.class).isEmpty() ) // no matching cadc account + { + log.debug("HttpPrincipal not found - dropping to anon: " + subject); + subject = AuthenticationUtil.getAnonSubject(); + } + } + + return subject; + } + + protected void augmentSubject(final Subject subject) + { + try + { + PrivilegedExceptionAction<Object> action = + new PrivilegedExceptionAction<Object>() + { + public Object run() throws Exception + { + try + { + LdapUserPersistence<Principal> dao = new LdapUserPersistence<Principal>(); + User<Principal> user = dao.getUser(subject.getPrincipals().iterator().next()); + subject.getPrincipals().addAll(user.getIdentities()); + } + catch (UserNotFoundException e) + { + // ignore, could be an anonymous user + } + return null; + } + }; + + Subject.doAs(subject, action); + } + catch (PrivilegedActionException e) + { + String msg = "Error augmenting subject " + subject; + throw new RuntimeException(msg, e); + } + } + +}