X-Git-Url: http://git.argeo.org/?a=blobdiff_plain;ds=sidebyside;f=org.argeo.cms%2Fsrc%2Forg%2Fargeo%2Fcms%2Finternal%2Fkernel%2FNodeHttp.java;h=6dc70144ba3ef6f7ee8f84cc8d189b5647a54c42;hb=92ac99f3ededbcd28def2bf9601bb33c02a351b3;hp=9a35e279ce28164ba6d53c79367c3b0f1021a2f8;hpb=91f477703e7b86048f15c16020f6a6f874b7fc1a;p=lgpl%2Fargeo-commons.git diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeHttp.java b/org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeHttp.java index 9a35e279c..6dc70144b 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeHttp.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeHttp.java @@ -1,14 +1,25 @@ package org.argeo.cms.internal.kernel; -import static org.argeo.jackrabbit.servlet.WebdavServlet.INIT_PARAM_RESOURCE_CONFIG; +import static org.argeo.cms.KernelHeader.ACCESS_CONTROL_CONTEXT; import java.io.IOException; +import java.security.AccessControlContext; +import java.security.AccessController; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; import java.security.cert.X509Certificate; import java.util.Enumeration; import java.util.Properties; import java.util.StringTokenizer; import javax.jcr.Repository; +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.LoginContext; +import javax.security.auth.login.LoginException; import javax.servlet.FilterChain; import javax.servlet.Servlet; import javax.servlet.ServletException; @@ -20,17 +31,13 @@ import org.apache.commons.codec.binary.Base64; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.argeo.cms.CmsException; +import org.argeo.cms.KernelHeader; import org.argeo.jackrabbit.servlet.OpenInViewSessionProvider; import org.argeo.jackrabbit.servlet.RemotingServlet; import org.argeo.jackrabbit.servlet.WebdavServlet; import org.argeo.jcr.ArgeoJcrConstants; -import org.argeo.security.NodeAuthenticationToken; import org.eclipse.equinox.http.servlet.ExtendedHttpService; import org.osgi.service.http.NamespaceException; -import org.springframework.security.authentication.AuthenticationManager; -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.context.SecurityContextHolder; /** * Intercepts and enriches http access, mainly focusing on security and @@ -43,7 +50,7 @@ class NodeHttp implements KernelConstants, ArgeoJcrConstants { private final static String HEADER_AUTHORIZATION = "Authorization"; private final static String HEADER_WWW_AUTHENTICATE = "WWW-Authenticate"; - private final AuthenticationManager authenticationManager; + // private final AuthenticationManager authenticationManager; private final ExtendedHttpService httpService; // FIXME Make it more unique @@ -57,10 +64,9 @@ class NodeHttp implements KernelConstants, ArgeoJcrConstants { // WebDav / JCR remoting private OpenInViewSessionProvider sessionProvider; - NodeHttp(ExtendedHttpService httpService, JackrabbitNode node, - NodeSecurity authenticationManager) { + NodeHttp(ExtendedHttpService httpService, JackrabbitNode node) { // this.bundleContext = bundleContext; - this.authenticationManager = authenticationManager; + // this.authenticationManager = authenticationManager; this.httpService = httpService; @@ -108,7 +114,7 @@ class NodeHttp implements KernelConstants, ArgeoJcrConstants { String pathPrefix = anonymous ? WEBDAV_PUBLIC : WEBDAV_PRIVATE; String path = pathPrefix + "/" + alias; Properties ip = new Properties(); - ip.setProperty(INIT_PARAM_RESOURCE_CONFIG, WEBDAV_CONFIG); + ip.setProperty(WebdavServlet.INIT_PARAM_RESOURCE_CONFIG, WEBDAV_CONFIG); ip.setProperty(WebdavServlet.INIT_PARAM_RESOURCE_PATH_PREFIX, path); httpService.registerFilter(path, anonymous ? new AnonymousFilter() : new DavFilter(), null, null); @@ -149,24 +155,35 @@ class NodeHttp implements KernelConstants, ArgeoJcrConstants { httpSession.setAttribute(ATTR_AUTH, Boolean.TRUE); } - private NodeAuthenticationToken basicAuth(String authHeader) { + private CallbackHandler basicAuth(String authHeader) { if (authHeader != null) { StringTokenizer st = new StringTokenizer(authHeader); if (st.hasMoreTokens()) { String basic = st.nextToken(); if (basic.equalsIgnoreCase("Basic")) { try { + // TODO manipulate char[] String credentials = new String(Base64.decodeBase64(st .nextToken()), "UTF-8"); // log.debug("Credentials: " + credentials); int p = credentials.indexOf(":"); if (p != -1) { - String login = credentials.substring(0, p).trim(); - String password = credentials.substring(p + 1) + final String login = credentials.substring(0, p) .trim(); - - return new NodeAuthenticationToken(login, - password.toCharArray()); + final char[] password = credentials + .substring(p + 1).trim().toCharArray(); + + return new CallbackHandler() { + public void handle(Callback[] callbacks) { + for (Callback cb : callbacks) { + if (cb instanceof NameCallback) + ((NameCallback) cb).setName(login); + else if (cb instanceof PasswordCallback) + ((PasswordCallback) cb) + .setPassword(password); + } + } + }; } else { throw new CmsException( "Invalid authentication token"); @@ -275,8 +292,10 @@ class NodeHttp implements KernelConstants, ArgeoJcrConstants { private class AnonymousFilter extends HttpFilter { @Override public void doFilter(HttpSession httpSession, - HttpServletRequest request, HttpServletResponse response, - FilterChain filterChain) throws IOException, ServletException { + final HttpServletRequest request, + final HttpServletResponse response, + final FilterChain filterChain) throws IOException, + ServletException { // Authenticate from session // if (isSessionAuthenticated(httpSession)) { @@ -284,8 +303,22 @@ class NodeHttp implements KernelConstants, ArgeoJcrConstants { // return; // } - KernelUtils.anonymousLogin(authenticationManager); - filterChain.doFilter(request, response); + Subject subject = KernelUtils.anonymousLogin(); + try { + Subject.doAs(subject, new PrivilegedExceptionAction() { + public Void run() throws IOException, ServletException { + filterChain.doFilter(request, response); + return null; + } + }); + } catch (PrivilegedActionException e) { + if (e.getCause() instanceof ServletException) + throw (ServletException) e.getCause(); + else if (e.getCause() instanceof IOException) + throw (IOException) e.getCause(); + else + throw new CmsException("Unexpected exception", e.getCause()); + } } } @@ -293,30 +326,59 @@ class NodeHttp implements KernelConstants, ArgeoJcrConstants { private class DavFilter extends HttpFilter { @Override - public void doFilter(HttpSession httpSession, - HttpServletRequest request, HttpServletResponse response, - FilterChain filterChain) throws IOException, ServletException { - - // Authenticate from session - // if (isSessionAuthenticated(httpSession)) { - // filterChain.doFilter(request, response); - // return; - // } - - // Process basic auth - String basicAuth = request.getHeader(HEADER_AUTHORIZATION); - if (basicAuth != null) { - UsernamePasswordAuthenticationToken token = basicAuth(basicAuth); - Authentication auth = authenticationManager.authenticate(token); - SecurityContextHolder.getContext().setAuthentication(auth); - // httpSession.setAttribute(SPRING_SECURITY_CONTEXT_KEY, - // SecurityContextHolder.getContext()); - // httpSession.setAttribute(ATTR_AUTH, Boolean.FALSE); - filterChain.doFilter(request, response); - return; + public void doFilter(final HttpSession httpSession, + final HttpServletRequest request, + final HttpServletResponse response, + final FilterChain filterChain) throws IOException, + ServletException { + + AccessControlContext acc = (AccessControlContext) httpSession + .getAttribute(KernelHeader.ACCESS_CONTROL_CONTEXT); + final Subject subject; + if (acc != null) { + subject = Subject.getSubject(acc); + } else { + // Process basic auth + String basicAuth = request.getHeader(HEADER_AUTHORIZATION); + if (basicAuth != null) { + CallbackHandler token = basicAuth(basicAuth); + try { + LoginContext lc = new LoginContext( + KernelHeader.LOGIN_CONTEXT_USER, token); + lc.login(); + subject = lc.getSubject(); + } catch (LoginException e) { + throw new CmsException("Could not login", e); + } + } else { + requestBasicAuth(httpSession, response); + return; + } + } + // do filter as subject + try { + Subject.doAs(subject, + new PrivilegedExceptionAction() { + public Void run() throws IOException, + ServletException { + // add security context to session + httpSession.setAttribute( + ACCESS_CONTROL_CONTEXT, + AccessController.getContext()); + filterChain.doFilter(request, response); + return null; + } + }); + } catch (PrivilegedActionException e) { + if (e.getCause() instanceof ServletException) + throw (ServletException) e.getCause(); + else if (e.getCause() instanceof IOException) + throw (IOException) e.getCause(); + else + throw new CmsException("Unexpected exception", + e.getCause()); } - requestBasicAuth(httpSession, response); } }