/*******************************************************************************
* Copyright (c) 2011, 2014 IBM Corporation and others
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.orion.server.servlets;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.orion.internal.server.servlets.Activator;
import org.eclipse.orion.internal.server.servlets.workspace.authorization.AuthorizationService;
import org.eclipse.orion.server.authentication.IAuthenticationService;
import org.eclipse.orion.server.core.EncodingUtils;
import org.eclipse.orion.server.core.LogHelper;
import org.eclipse.orion.server.core.ProtocolConstants;
import org.eclipse.orion.server.core.ServerStatus;
import org.json.JSONException;
import org.json.JSONObject;
import org.osgi.framework.Version;
import org.osgi.service.http.HttpContext;
/**
* The filter checks whether the request is made by an authorized user.
*/
public class AuthorizedUserFilter implements Filter {
private IAuthenticationService authenticationService;
public void init(FilterConfig filterConfig) throws ServletException {
authenticationService = Activator.getDefault().getAuthService();
// treat lack of authentication as an error. Administrator should use
// "None" to disable authentication entirely
if (authenticationService == null) {
String msg = "Authentication service is missing. The server configuration must specify an authentication scheme, or use \"None\" to indicate no authentication"; //$NON-NLS-1$
LogHelper.log(new Status(IStatus.ERROR, Activator.PI_SERVER_SERVLETS, msg, null));
throw new ServletException(msg);
}
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
String remoteUser = httpRequest.getRemoteUser();
String userName = remoteUser;
if (userName == null) {
userName = authenticationService.getAuthenticatedUser(httpRequest, httpResponse);
if (userName == null)
userName = IAuthenticationService.ANONYMOUS_LOGIN_VALUE;
}
try {
String requestPath = httpRequest.getServletPath() + (httpRequest.getPathInfo() == null ? "" : httpRequest.getPathInfo());
if (!AuthorizationService.checkRights(userName, requestPath, httpRequest.getMethod())) {
if (IAuthenticationService.ANONYMOUS_LOGIN_VALUE.equals(userName)) {
userName = authenticationService.authenticateUser(httpRequest, httpResponse);
if (userName == null)
return;
} else {
setNotAuthorized(httpRequest, httpResponse, requestPath);
return;
}
}
String xCreateOptions = httpRequest.getHeader("X-Create-Options");
if (xCreateOptions != null) {
String sourceLocation = null;;
try {
String method = xCreateOptions.contains("move") ? "POST" : "GET";
JSONObject requestObject = OrionServlet.readJSONRequest(httpRequest);
sourceLocation = requestObject.getString(ProtocolConstants.KEY_LOCATION);
String normalizedLocation = new URI(sourceLocation).normalize().getPath();
normalizedLocation = normalizedLocation.startsWith(httpRequest.getContextPath()) ? normalizedLocation.substring(httpRequest.getContextPath().length()) : null;
if (normalizedLocation == null || !AuthorizationService.checkRights(userName, normalizedLocation, method)) {
setNotAuthorized(httpRequest, httpResponse, sourceLocation);
return;
}
} catch (URISyntaxException e) {
setNotAuthorized(httpRequest, httpResponse, sourceLocation);
return;
} catch (JSONException e) {
// ignore, and fall through
}
}
if (remoteUser == null && !IAuthenticationService.ANONYMOUS_LOGIN_VALUE.equals(userName)) {
request.setAttribute(HttpContext.REMOTE_USER, userName);
request.setAttribute(HttpContext.AUTHENTICATION_TYPE, authenticationService.getAuthType());
}
} catch (CoreException e) {
httpResponse.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
return;
}
chain.doFilter(request, response);
}
private void setNotAuthorized(HttpServletRequest req, HttpServletResponse resp, String resourceURL) throws IOException {
String versionString = req.getHeader("Orion-Version"); //$NON-NLS-1$
Version version = versionString == null ? null : new Version(versionString);
// TODO: This is a workaround for calls
// that does not include the WebEclipse version header
String xRequestedWith = req.getHeader("X-Requested-With"); //$NON-NLS-1$
String msg = "You are not authorized to access " + resourceURL;
if (version == null && !"XMLHttpRequest".equals(xRequestedWith)) { //$NON-NLS-1$
resp.sendError(HttpServletResponse.SC_FORBIDDEN, msg);
} else {
resp.setContentType(ProtocolConstants.CONTENT_TYPE_JSON);
ServerStatus serverStatus = new ServerStatus(IStatus.ERROR, HttpServletResponse.SC_FORBIDDEN, EncodingUtils.encodeForHTML(msg), null);
resp.setStatus(HttpServletResponse.SC_FORBIDDEN);
resp.getWriter().print(serverStatus.toJSON().toString());
}
}
public void destroy() {
// TODO Auto-generated method stub
}
}