You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

RpcFilter.java 5.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. /*
  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.servlet;
  17. import java.io.IOException;
  18. import java.text.MessageFormat;
  19. import com.google.inject.Inject;
  20. import com.google.inject.Singleton;
  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. import com.gitblit.Constants.RpcRequest;
  28. import com.gitblit.IStoredSettings;
  29. import com.gitblit.Keys;
  30. import com.gitblit.manager.IAuthenticationManager;
  31. import com.gitblit.manager.IRuntimeManager;
  32. import com.gitblit.models.UserModel;
  33. /**
  34. * The RpcFilter is a servlet filter that secures the RpcServlet.
  35. *
  36. * The filter extracts the rpc request type from the url and determines if the
  37. * requested action requires a Basic authentication prompt. If authentication is
  38. * required and no credentials are stored in the "Authorization" header, then a
  39. * basic authentication challenge is issued.
  40. *
  41. * http://en.wikipedia.org/wiki/Basic_access_authentication
  42. *
  43. * @author James Moger
  44. *
  45. */
  46. @Singleton
  47. public class RpcFilter extends AuthenticationFilter {
  48. private IStoredSettings settings;
  49. private IRuntimeManager runtimeManager;
  50. @Inject
  51. public RpcFilter(
  52. IStoredSettings settings,
  53. IRuntimeManager runtimeManager,
  54. IAuthenticationManager authenticationManager) {
  55. super(authenticationManager);
  56. this.settings = settings;
  57. this.runtimeManager = runtimeManager;
  58. }
  59. /**
  60. * doFilter does the actual work of preprocessing the request to ensure that
  61. * the user may proceed.
  62. *
  63. * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest,
  64. * javax.servlet.ServletResponse, javax.servlet.FilterChain)
  65. */
  66. @Override
  67. public void doFilter(final ServletRequest request, final ServletResponse response,
  68. final FilterChain chain) throws IOException, ServletException {
  69. HttpServletRequest httpRequest = (HttpServletRequest) request;
  70. HttpServletResponse httpResponse = (HttpServletResponse) response;
  71. String fullUrl = getFullUrl(httpRequest);
  72. RpcRequest requestType = RpcRequest.fromName(httpRequest.getParameter("req"));
  73. if (requestType == null) {
  74. httpResponse.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED);
  75. return;
  76. }
  77. boolean adminRequest = requestType.exceeds(RpcRequest.LIST_SETTINGS);
  78. // conditionally reject all rpc requests
  79. if (!settings.getBoolean(Keys.web.enableRpcServlet, true)) {
  80. logger.warn(Keys.web.enableRpcServlet + " must be set TRUE for rpc requests.");
  81. httpResponse.sendError(HttpServletResponse.SC_FORBIDDEN);
  82. return;
  83. }
  84. boolean authenticateView = settings.getBoolean(Keys.web.authenticateViewPages, false);
  85. boolean authenticateAdmin = settings.getBoolean(Keys.web.authenticateAdminPages, true);
  86. // Wrap the HttpServletRequest with the RpcServletRequest which
  87. // overrides the servlet container user principal methods.
  88. AuthenticatedRequest authenticatedRequest = new AuthenticatedRequest(httpRequest);
  89. UserModel user = getUser(httpRequest);
  90. if (user != null) {
  91. authenticatedRequest.setUser(user);
  92. }
  93. // conditionally reject rpc management/administration requests
  94. if (adminRequest && !settings.getBoolean(Keys.web.enableRpcManagement, false)) {
  95. logger.warn(MessageFormat.format("{0} must be set TRUE for {1} rpc requests.",
  96. Keys.web.enableRpcManagement, requestType.toString()));
  97. httpResponse.sendError(HttpServletResponse.SC_FORBIDDEN);
  98. return;
  99. }
  100. // BASIC authentication challenge and response processing
  101. if ((adminRequest && authenticateAdmin) || (!adminRequest && authenticateView)) {
  102. if (user == null) {
  103. // challenge client to provide credentials. send 401.
  104. if (runtimeManager.isDebugMode()) {
  105. logger.info(MessageFormat.format("RPC: CHALLENGE {0}", fullUrl));
  106. }
  107. httpResponse.setHeader("WWW-Authenticate", CHALLENGE);
  108. httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED);
  109. return;
  110. } else {
  111. // check user access for request
  112. if (user.canAdmin() || canAccess(user, requestType)) {
  113. // authenticated request permitted.
  114. // pass processing to the restricted servlet.
  115. newSession(authenticatedRequest, httpResponse);
  116. logger.info(MessageFormat.format("RPC: {0} ({1}) authenticated", fullUrl,
  117. HttpServletResponse.SC_CONTINUE));
  118. chain.doFilter(authenticatedRequest, httpResponse);
  119. return;
  120. }
  121. // valid user, but not for requested access. send 403.
  122. logger.warn(MessageFormat.format("RPC: {0} forbidden to access {1}",
  123. user.username, fullUrl));
  124. httpResponse.sendError(HttpServletResponse.SC_FORBIDDEN);
  125. return;
  126. }
  127. }
  128. if (runtimeManager.isDebugMode()) {
  129. logger.info(MessageFormat.format("RPC: {0} ({1}) unauthenticated", fullUrl,
  130. HttpServletResponse.SC_CONTINUE));
  131. }
  132. // unauthenticated request permitted.
  133. // pass processing to the restricted servlet.
  134. chain.doFilter(authenticatedRequest, httpResponse);
  135. }
  136. private boolean canAccess(UserModel user, RpcRequest requestType) {
  137. switch (requestType) {
  138. case GET_PROTOCOL:
  139. return true;
  140. case LIST_REPOSITORIES:
  141. return true;
  142. default:
  143. return user.canAdmin();
  144. }
  145. }
  146. }