James Moger
2012-09-10 fabe060d3a435f116128851f828e35c2af5fde67
commit | author | age
8c9a20 1 /*
JM 2  * Copyright 2011 gitblit.com.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.gitblit;
17
13a3f5 18 import java.io.IOException;
JM 19 import java.text.MessageFormat;
20
21 import javax.servlet.FilterChain;
22 import javax.servlet.ServletException;
23 import javax.servlet.ServletRequest;
24 import javax.servlet.ServletResponse;
25 import javax.servlet.http.HttpServletRequest;
26 import javax.servlet.http.HttpServletResponse;
27
8c9a20 28 import com.gitblit.Constants.AccessRestrictionType;
13a3f5 29 import com.gitblit.models.ProjectModel;
8c9a20 30 import com.gitblit.models.RepositoryModel;
JM 31 import com.gitblit.models.UserModel;
32
892570 33 /**
13a3f5 34  * The SyndicationFilter is an AuthenticationFilter which ensures that feed
JM 35  * requests for projects or view-restricted repositories have proper authentication
892570 36  * credentials and are authorized for the requested feed.
JM 37  * 
38  * @author James Moger
39  * 
40  */
13a3f5 41 public class SyndicationFilter extends AuthenticationFilter {
8c9a20 42
892570 43     /**
JM 44      * Extract the repository name from the url.
45      * 
46      * @param url
47      * @return repository name
48      */
13a3f5 49     protected String extractRequestedName(String url) {
565ee0 50         if (url.indexOf('?') > -1) {
JM 51             return url.substring(0, url.indexOf('?'));
52         }
8c9a20 53         return url;
JM 54     }
55
892570 56     /**
13a3f5 57      * doFilter does the actual work of preprocessing the request to ensure that
JM 58      * the user may proceed.
892570 59      * 
13a3f5 60      * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest,
JM 61      *      javax.servlet.ServletResponse, javax.servlet.FilterChain)
892570 62      */
8c9a20 63     @Override
13a3f5 64     public void doFilter(final ServletRequest request, final ServletResponse response,
JM 65             final FilterChain chain) throws IOException, ServletException {
8c9a20 66
13a3f5 67         HttpServletRequest httpRequest = (HttpServletRequest) request;
JM 68         HttpServletResponse httpResponse = (HttpServletResponse) response;
8c9a20 69
13a3f5 70         String fullUrl = getFullUrl(httpRequest);
JM 71         String name = extractRequestedName(fullUrl);
8c9a20 72
13a3f5 73         ProjectModel project = GitBlit.self().getProjectModel(name);
JM 74         RepositoryModel model = null;
75         
76         if (project == null) {
77             // try loading a repository model
78             model = GitBlit.self().getRepositoryModel(name);
79             if (model == null) {
80                 // repository not found. send 404.
81                 logger.info(MessageFormat.format("ARF: {0} ({1})", fullUrl,
82                         HttpServletResponse.SC_NOT_FOUND));
83                 httpResponse.sendError(HttpServletResponse.SC_NOT_FOUND);
84                 return;
85             }
86         }
87         
88         // Wrap the HttpServletRequest with the AccessRestrictionRequest which
89         // overrides the servlet container user principal methods.
90         // JGit requires either:
91         //
92         // 1. servlet container authenticated user
93         // 2. http.receivepack = true in each repository's config
94         //
95         // Gitblit must conditionally authenticate users per-repository so just
96         // enabling http.receivepack is insufficient.
97         AuthenticatedRequest authenticatedRequest = new AuthenticatedRequest(httpRequest);
98         UserModel user = getUser(httpRequest);
99         if (user != null) {
100             authenticatedRequest.setUser(user);
101         }
102
103         // BASIC authentication challenge and response processing
104         if (model != null) {
105             if (model.accessRestriction.atLeast(AccessRestrictionType.VIEW)) {
106                 if (user == null) {
107                     // challenge client to provide credentials. send 401.
108                     if (GitBlit.isDebugMode()) {
109                         logger.info(MessageFormat.format("ARF: CHALLENGE {0}", fullUrl));
110                     }
111                     httpResponse.setHeader("WWW-Authenticate", CHALLENGE);
112                     httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED);
113                     return;
114                 } else {
115                     // check user access for request
116                     if (user.canAdmin || user.canAccessRepository(model)) {
117                         // authenticated request permitted.
118                         // pass processing to the restricted servlet.
119                         newSession(authenticatedRequest, httpResponse);
120                         logger.info(MessageFormat.format("ARF: {0} ({1}) authenticated", fullUrl,
121                                 HttpServletResponse.SC_CONTINUE));
122                         chain.doFilter(authenticatedRequest, httpResponse);
123                         return;
124                     }
125                     // valid user, but not for requested access. send 403.
126                     if (GitBlit.isDebugMode()) {
127                         logger.info(MessageFormat.format("ARF: {0} forbidden to access {1}",
128                                 user.username, fullUrl));
129                     }
130                     httpResponse.sendError(HttpServletResponse.SC_FORBIDDEN);
131                     return;
132                 }
133             }
134         }
135
136         if (GitBlit.isDebugMode()) {
137             logger.info(MessageFormat.format("ARF: {0} ({1}) unauthenticated", fullUrl,
138                     HttpServletResponse.SC_CONTINUE));
139         }
140         // unauthenticated request permitted.
141         // pass processing to the restricted servlet.
142         chain.doFilter(authenticatedRequest, httpResponse);
143     }
8c9a20 144 }