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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  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 javax.inject.Inject;
  20. import javax.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.IRuntimeManager;
  31. import com.gitblit.manager.IAuthenticationManager;
  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 final IStoredSettings settings;
  49. private final IRuntimeManager runtimeManager;
  50. @Inject
  51. public RpcFilter(
  52. IRuntimeManager runtimeManager,
  53. IAuthenticationManager authenticationManager) {
  54. super(authenticationManager);
  55. this.settings = runtimeManager.getSettings();
  56. this.runtimeManager = runtimeManager;
  57. }
  58. /**
  59. * doFilter does the actual work of preprocessing the request to ensure that
  60. * the user may proceed.
  61. *
  62. * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest,
  63. * javax.servlet.ServletResponse, javax.servlet.FilterChain)
  64. */
  65. @Override
  66. public void doFilter(final ServletRequest request, final ServletResponse response,
  67. final FilterChain chain) throws IOException, ServletException {
  68. HttpServletRequest httpRequest = (HttpServletRequest) request;
  69. HttpServletResponse httpResponse = (HttpServletResponse) response;
  70. String fullUrl = getFullUrl(httpRequest);
  71. RpcRequest requestType = RpcRequest.fromName(httpRequest.getParameter("req"));
  72. if (requestType == null) {
  73. httpResponse.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED);
  74. return;
  75. }
  76. boolean adminRequest = requestType.exceeds(RpcRequest.LIST_SETTINGS);
  77. // conditionally reject all rpc requests
  78. if (!settings.getBoolean(Keys.web.enableRpcServlet, true)) {
  79. logger.warn(Keys.web.enableRpcServlet + " must be set TRUE for rpc requests.");
  80. httpResponse.sendError(HttpServletResponse.SC_FORBIDDEN);
  81. return;
  82. }
  83. boolean authenticateView = settings.getBoolean(Keys.web.authenticateViewPages, false);
  84. boolean authenticateAdmin = settings.getBoolean(Keys.web.authenticateAdminPages, true);
  85. // Wrap the HttpServletRequest with the RpcServletRequest which
  86. // overrides the servlet container user principal methods.
  87. AuthenticatedRequest authenticatedRequest = new AuthenticatedRequest(httpRequest);
  88. UserModel user = getUser(httpRequest);
  89. if (user != null) {
  90. authenticatedRequest.setUser(user);
  91. }
  92. // conditionally reject rpc management/administration requests
  93. if (adminRequest && !settings.getBoolean(Keys.web.enableRpcManagement, false)) {
  94. logger.warn(MessageFormat.format("{0} must be set TRUE for {1} rpc requests.",
  95. Keys.web.enableRpcManagement, requestType.toString()));
  96. httpResponse.sendError(HttpServletResponse.SC_FORBIDDEN);
  97. return;
  98. }
  99. // BASIC authentication challenge and response processing
  100. if ((adminRequest && authenticateAdmin) || (!adminRequest && authenticateView)) {
  101. if (user == null) {
  102. // challenge client to provide credentials. send 401.
  103. if (runtimeManager.isDebugMode()) {
  104. logger.info(MessageFormat.format("RPC: CHALLENGE {0}", fullUrl));
  105. }
  106. httpResponse.setHeader("WWW-Authenticate", CHALLENGE);
  107. httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED);
  108. return;
  109. } else {
  110. // check user access for request
  111. if (user.canAdmin() || canAccess(user, requestType)) {
  112. // authenticated request permitted.
  113. // pass processing to the restricted servlet.
  114. newSession(authenticatedRequest, httpResponse);
  115. logger.info(MessageFormat.format("RPC: {0} ({1}) authenticated", fullUrl,
  116. HttpServletResponse.SC_CONTINUE));
  117. chain.doFilter(authenticatedRequest, httpResponse);
  118. return;
  119. }
  120. // valid user, but not for requested access. send 403.
  121. logger.warn(MessageFormat.format("RPC: {0} forbidden to access {1}",
  122. user.username, fullUrl));
  123. httpResponse.sendError(HttpServletResponse.SC_FORBIDDEN);
  124. return;
  125. }
  126. }
  127. if (runtimeManager.isDebugMode()) {
  128. logger.info(MessageFormat.format("RPC: {0} ({1}) unauthenticated", fullUrl,
  129. HttpServletResponse.SC_CONTINUE));
  130. }
  131. // unauthenticated request permitted.
  132. // pass processing to the restricted servlet.
  133. chain.doFilter(authenticatedRequest, httpResponse);
  134. }
  135. private boolean canAccess(UserModel user, RpcRequest requestType) {
  136. switch (requestType) {
  137. case GET_PROTOCOL:
  138. return true;
  139. case LIST_REPOSITORIES:
  140. return true;
  141. default:
  142. return user.canAdmin();
  143. }
  144. }
  145. }