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;
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
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
// 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;
try {
httpService.registerFilter("/", rootFilter, null, null);
} catch (Exception e) {
- throw new CmsException(
- "Could not register root filter", e);
+ throw new CmsException("Could not register root filter", e);
}
}
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);
httpService.registerServlet(path, (Servlet) remotingServlet, ip, null);
}
-// private Boolean isSessionAuthenticated(HttpSession httpSession) {
-// SecurityContext contextFromSession = (SecurityContext) httpSession
-// .getAttribute(SPRING_SECURITY_CONTEXT_KEY);
-// return contextFromSession != null;
-// }
+ // private Boolean isSessionAuthenticated(HttpSession httpSession) {
+ // SecurityContext contextFromSession = (SecurityContext) httpSession
+ // .getAttribute(SPRING_SECURITY_CONTEXT_KEY);
+ // return contextFromSession != null;
+ // }
private void requestBasicAuth(HttpSession httpSession,
HttpServletResponse response) {
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");
public void doFilter(HttpSession httpSession,
HttpServletRequest request, HttpServletResponse response,
FilterChain filterChain) throws IOException, ServletException {
- if (log.isTraceEnabled())
+ if (log.isTraceEnabled()) {
+ log.trace(request.getRequestURL().append(
+ request.getQueryString() != null ? "?"
+ + request.getQueryString() : ""));
logRequest(request);
+ }
String servletPath = request.getServletPath();
int pathLength = path.length();
if (pathLength != 0 && (path.charAt(0) == '/')
&& !servletPath.endsWith("rwt-resources")
- && !path.equals("/")) {
+ && path.lastIndexOf('/') != 0) {
String newLocation = request.getServletPath() + "#" + path;
response.setHeader("Location", newLocation);
response.setStatus(HttpServletResponse.SC_FOUND);
}
private void logRequest(HttpServletRequest request) {
- log.debug(request.getContextPath());
- log.debug(request.getServletPath());
- log.debug(request.getRequestURI());
- log.debug(request.getQueryString());
+ log.debug("contextPath=" + request.getContextPath());
+ log.debug("servletPath=" + request.getServletPath());
+ log.debug("requestURI=" + request.getRequestURI());
+ log.debug("queryString=" + request.getQueryString());
StringBuilder buf = new StringBuilder();
// headers
Enumeration<String> en = request.getHeaderNames();
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)) {
-// filterChain.doFilter(request, response);
-// return;
-// }
+ // if (isSessionAuthenticated(httpSession)) {
+ // filterChain.doFilter(request, response);
+ // return;
+ // }
- KernelUtils.anonymousLogin(authenticationManager);
- filterChain.doFilter(request, response);
+ Subject subject = KernelUtils.anonymousLogin();
+ try {
+ Subject.doAs(subject, new PrivilegedExceptionAction<Void>() {
+ 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());
+ }
}
}
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<Void>() {
+ 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);
}
}