From 9effe1630d97039b3e01cd9b58ed07e75be1d63c Mon Sep 17 00:00:00 2001 From: James Moger <james.moger@gitblit.com> Date: Mon, 25 Feb 2013 08:40:30 -0500 Subject: [PATCH] Merge pull request #75 from thefake/master --- src/com/gitblit/SyndicationFilter.java | 128 ++++++++++++++++++++++++++++++++++++++---- 1 files changed, 114 insertions(+), 14 deletions(-) diff --git a/src/com/gitblit/SyndicationFilter.java b/src/com/gitblit/SyndicationFilter.java index 68f383b..61bf225 100644 --- a/src/com/gitblit/SyndicationFilter.java +++ b/src/com/gitblit/SyndicationFilter.java @@ -15,30 +15,130 @@ */ package com.gitblit; +import java.io.IOException; +import java.text.MessageFormat; + +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + import com.gitblit.Constants.AccessRestrictionType; +import com.gitblit.models.ProjectModel; import com.gitblit.models.RepositoryModel; import com.gitblit.models.UserModel; -public class SyndicationFilter extends AccessRestrictionFilter { +/** + * The SyndicationFilter is an AuthenticationFilter which ensures that feed + * requests for projects or view-restricted repositories have proper authentication + * credentials and are authorized for the requested feed. + * + * @author James Moger + * + */ +public class SyndicationFilter extends AuthenticationFilter { - @Override - protected String extractRepositoryName(String url) { + /** + * Extract the repository name from the url. + * + * @param url + * @return repository name + */ + protected String extractRequestedName(String url) { + if (url.indexOf('?') > -1) { + return url.substring(0, url.indexOf('?')); + } return url; } + /** + * doFilter does the actual work of preprocessing the request to ensure that + * the user may proceed. + * + * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, + * javax.servlet.ServletResponse, javax.servlet.FilterChain) + */ @Override - protected String getUrlRequestType(String url) { - return "RESTRICTED"; - } + public void doFilter(final ServletRequest request, final ServletResponse response, + final FilterChain chain) throws IOException, ServletException { - @Override - protected boolean requiresAuthentication(RepositoryModel repository) { - return repository.accessRestriction.atLeast(AccessRestrictionType.VIEW); - } + HttpServletRequest httpRequest = (HttpServletRequest) request; + HttpServletResponse httpResponse = (HttpServletResponse) response; - @Override - protected boolean canAccess(RepositoryModel repository, UserModel user, String restrictedURL) { - return user.canAccessRepository(repository.name); - } + String fullUrl = getFullUrl(httpRequest); + String name = extractRequestedName(fullUrl); + ProjectModel project = GitBlit.self().getProjectModel(name); + RepositoryModel model = null; + + if (project == null) { + // try loading a repository model + model = GitBlit.self().getRepositoryModel(name); + if (model == null) { + // repository not found. send 404. + logger.info(MessageFormat.format("ARF: {0} ({1})", fullUrl, + HttpServletResponse.SC_NOT_FOUND)); + httpResponse.sendError(HttpServletResponse.SC_NOT_FOUND); + return; + } + } + + // Wrap the HttpServletRequest with the AccessRestrictionRequest which + // overrides the servlet container user principal methods. + // JGit requires either: + // + // 1. servlet container authenticated user + // 2. http.receivepack = true in each repository's config + // + // Gitblit must conditionally authenticate users per-repository so just + // enabling http.receivepack is insufficient. + AuthenticatedRequest authenticatedRequest = new AuthenticatedRequest(httpRequest); + UserModel user = getUser(httpRequest); + if (user != null) { + authenticatedRequest.setUser(user); + } + + // BASIC authentication challenge and response processing + if (model != null) { + if (model.accessRestriction.atLeast(AccessRestrictionType.VIEW)) { + if (user == null) { + // challenge client to provide credentials. send 401. + if (GitBlit.isDebugMode()) { + logger.info(MessageFormat.format("ARF: CHALLENGE {0}", fullUrl)); + } + httpResponse.setHeader("WWW-Authenticate", CHALLENGE); + httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED); + return; + } else { + // check user access for request + if (user.canView(model)) { + // authenticated request permitted. + // pass processing to the restricted servlet. + newSession(authenticatedRequest, httpResponse); + logger.info(MessageFormat.format("ARF: {0} ({1}) authenticated", fullUrl, + HttpServletResponse.SC_CONTINUE)); + chain.doFilter(authenticatedRequest, httpResponse); + return; + } + // valid user, but not for requested access. send 403. + if (GitBlit.isDebugMode()) { + logger.info(MessageFormat.format("ARF: {0} forbidden to access {1}", + user.username, fullUrl)); + } + httpResponse.sendError(HttpServletResponse.SC_FORBIDDEN); + return; + } + } + } + + if (GitBlit.isDebugMode()) { + logger.info(MessageFormat.format("ARF: {0} ({1}) unauthenticated", fullUrl, + HttpServletResponse.SC_CONTINUE)); + } + // unauthenticated request permitted. + // pass processing to the restricted servlet. + chain.doFilter(authenticatedRequest, httpResponse); + } } -- Gitblit v1.9.1