/**
  * Mark Request that processed at primary node with attribute primaryIndicatorName
  *
  * @param request
  * @throws IOException
  */
 protected void createPrimaryIndicator(Request request) throws IOException {
   String id = request.getRequestedSessionId();
   if ((id != null) && (id.length() > 0)) {
     Manager manager = request.getContext().getManager();
     Session session = manager.findSession(id);
     if (session instanceof ClusterSession) {
       ClusterSession cses = (ClusterSession) session;
       if (log.isDebugEnabled())
         log.debug(
             sm.getString(
                 "ReplicationValve.session.indicator",
                 request.getContext().getName(),
                 id,
                 primaryIndicatorName,
                 Boolean.valueOf(cses.isPrimarySession())));
       request.setAttribute(
           primaryIndicatorName, cses.isPrimarySession() ? Boolean.TRUE : Boolean.FALSE);
     } else {
       if (log.isDebugEnabled()) {
         if (session != null) {
           log.debug(
               sm.getString("ReplicationValve.session.found", request.getContext().getName(), id));
         } else {
           log.debug(
               sm.getString(
                   "ReplicationValve.session.invalid", request.getContext().getName(), id));
         }
       }
     }
   }
 }
Пример #2
0
  @Override
  public boolean authenticate(Request request, HttpServletResponse response, LoginConfig config)
      throws IOException {

    Principal principal = request.getUserPrincipal();
    if (principal != null) {
      log.info("User " + principal.getName() + " is already autenticated");
      return true;
    }

    Realm realm = request.getContext().getRealm();
    log.info("Authentication against " + realm.toString() + " realm: " + realm.getInfo());
    principal = realm.authenticate("user1", "password1");
    if (principal != null) {
      request.setUserPrincipal(principal);
      log.info("Authentication via custom valve authenticator");
      response.addHeader("valve", testparam);
      log.info(
          "Valve "
              + TestAuthenticator.class.getName()
              + " was hit and adding header parameter 'authenticated' with value "
              + testparam);
      return true;
    }
    log.warn("Login via global valve authenticator wasn't successfull");
    return false;
  }
  /**
   * Handle an HTTP status code or Java exception by forwarding control to the location included in
   * the specified errorPage object. It is assumed that the caller has already recorded any request
   * attributes that are to be forwarded to this page. Return <code>true</code> if we successfully
   * utilized the specified error page location, or <code>false</code> if the default error report
   * should be rendered.
   *
   * @param request The request being processed
   * @param response The response being generated
   * @param errorPage The errorPage directive we are obeying
   */
  private boolean custom(Request request, Response response, ErrorPage errorPage) {

    if (container.getLogger().isDebugEnabled())
      container.getLogger().debug("Processing " + errorPage);

    try {
      // Forward control to the specified location
      ServletContext servletContext = request.getContext().getServletContext();
      RequestDispatcher rd = servletContext.getRequestDispatcher(errorPage.getLocation());

      if (response.isCommitted()) {
        // Response is committed - including the error page is the
        // best we can do
        rd.include(request.getRequest(), response.getResponse());
      } else {
        // Reset the response (keeping the real error code and message)
        response.resetBuffer(true);
        response.setContentLength(-1);

        rd.forward(request.getRequest(), response.getResponse());

        // If we forward, the response is suspended again
        response.setSuspended(false);
      }

      // Indicate that we have successfully processed this custom page
      return (true);

    } catch (Throwable t) {
      ExceptionUtils.handleThrowable(t);
      // Report our failure to process this custom page
      container.getLogger().error("Exception Processing " + errorPage, t);
      return (false);
    }
  }
Пример #4
0
  public void invoke(Request request, Response response) throws IOException, ServletException {

    try {

      if (!alreadySetLogbackStatusManager) {
        alreadySetLogbackStatusManager = true;
        org.apache.catalina.Context tomcatContext = request.getContext();
        if (tomcatContext != null) {
          ServletContext sc = tomcatContext.getServletContext();
          if (sc != null) {
            sc.setAttribute(AccessConstants.LOGBACK_STATUS_MANAGER_KEY, getStatusManager());
          }
        }
      }

      getNext().invoke(request, response);

      TomcatServerAdapter adapter = new TomcatServerAdapter(request, response);
      AccessEvent accessEvent = new AccessEvent(request, response, adapter);

      if (getFilterChainDecision(accessEvent) == FilterReply.DENY) {
        return;
      }

      // TODO better exception handling
      aai.appendLoopOnAppenders(accessEvent);
    } finally {
      request.removeAttribute(AccessConstants.LOGBACK_STATUS_MANAGER_KEY);
    }
  }
  /**
   * Log the interesting request parameters, invoke the next Valve in the sequence, and log the
   * interesting response parameters.
   *
   * @param request The servlet request to be processed
   * @param response The servlet response to be created
   * @exception IOException if an input/output error occurs
   * @exception ServletException if a servlet error occurs
   */
  @Override
  public void invoke(Request request, Response response) throws IOException, ServletException {
    long totalstart = 0;

    // this happens before the request
    if (doStatistics()) {
      totalstart = System.currentTimeMillis();
    }
    if (primaryIndicator) {
      createPrimaryIndicator(request);
    }
    Context context = request.getContext();
    boolean isCrossContext =
        context != null
            && context instanceof StandardContext
            && ((StandardContext) context).getCrossContext();
    try {
      if (isCrossContext) {
        if (log.isDebugEnabled()) log.debug(sm.getString("ReplicationValve.crossContext.add"));
        // FIXME add Pool of Arraylists
        crossContextSessions.set(new ArrayList<DeltaSession>());
      }
      getNext().invoke(request, response);
      if (context != null) {
        Manager manager = context.getManager();
        if (manager != null && manager instanceof ClusterManager) {
          ClusterManager clusterManager = (ClusterManager) manager;
          CatalinaCluster containerCluster = (CatalinaCluster) getContainer().getCluster();
          if (containerCluster == null) {
            if (log.isWarnEnabled()) log.warn(sm.getString("ReplicationValve.nocluster"));
            return;
          }
          // valve cluster can access manager - other cluster handle replication
          // at host level - hopefully!
          if (containerCluster.getManager(clusterManager.getName()) == null) return;
          if (containerCluster.hasMembers()) {
            sendReplicationMessage(
                request, totalstart, isCrossContext, clusterManager, containerCluster);
          } else {
            resetReplicationRequest(request, isCrossContext);
          }
        }
      }
    } finally {
      // Array must be remove: Current master request send endAccess at recycle.
      // Don't register this request session again!
      if (isCrossContext) {
        if (log.isDebugEnabled()) log.debug(sm.getString("ReplicationValve.crossContext.remove"));
        // crossContextSessions.remove() only exist at Java 5
        // register ArrayList at a pool
        crossContextSessions.set(null);
      }
    }
  }
  /**
   * Handle the HTTP status code (and corresponding message) generated while processing the
   * specified Request to produce the specified Response. Any exceptions that occur during
   * generation of the error report are logged and swallowed.
   *
   * @param request The request being processed
   * @param response The response being generated
   */
  private void status(Request request, Response response) {

    int statusCode = response.getStatus();

    // Handle a custom error page for this status code
    Context context = request.getContext();
    if (context == null) return;

    /* Only look for error pages when isError() is set.
     * isError() is set when response.sendError() is invoked. This
     * allows custom error pages without relying on default from
     * web.xml.
     */
    if (!response.isError()) return;

    ErrorPage errorPage = context.findErrorPage(statusCode);
    if (errorPage == null) {
      // Look for a default error page
      errorPage = context.findErrorPage(0);
    }
    if (errorPage != null && response.setErrorReported()) {
      response.setAppCommitted(false);
      request.setAttribute(RequestDispatcher.ERROR_STATUS_CODE, Integer.valueOf(statusCode));

      String message = response.getMessage();
      if (message == null) message = "";
      request.setAttribute(RequestDispatcher.ERROR_MESSAGE, message);
      request.setAttribute(Globals.DISPATCHER_REQUEST_PATH_ATTR, errorPage.getLocation());
      request.setAttribute(Globals.DISPATCHER_TYPE_ATTR, DispatcherType.ERROR);

      Wrapper wrapper = request.getWrapper();
      if (wrapper != null)
        request.setAttribute(RequestDispatcher.ERROR_SERVLET_NAME, wrapper.getName());
      request.setAttribute(RequestDispatcher.ERROR_REQUEST_URI, request.getRequestURI());
      if (custom(request, response, errorPage)) {
        try {
          response.finishResponse();
        } catch (ClientAbortException e) {
          // Ignore
        } catch (IOException e) {
          container.getLogger().warn("Exception Processing " + errorPage, e);
        }
      }
    }
  }
  @BeforeMethod
  public void setUp() throws Exception {
    _service = mock(MemcachedSessionService.class);
    _request = mock(Request.class);
    _response = mock(Response.class);

    final Context _contextContainer = mock(Context.class);
    final Host _hostContainer = mock(Host.class);
    final SessionManager _manager = mock(SessionManager.class);

    when(_service.getManager()).thenReturn(_manager);
    when(_manager.getContainer()).thenReturn(_contextContainer);
    when(_contextContainer.getParent()).thenReturn(_hostContainer);
    when(_contextContainer.getPath()).thenReturn("/");

    _sessionTrackerValve = createSessionTrackerValve();
    _nextValve = mock(Valve.class);
    _sessionTrackerValve.setNext(_nextValve);
    _sessionTrackerValve.setContainer(_hostContainer);
    _memcachedNodesManager = mock(MemcachedNodesManager.class);
    _sessionIdFormat = mock(SessionIdFormat.class);

    when(_request.getRequestURI()).thenReturn("/someRequest");
    when(_request.getMethod()).thenReturn("GET");
    when(_request.getQueryString()).thenReturn(null);
    when(_request.getContext()).thenReturn(_contextContainer);

    when(_request.getNote(eq(RequestTrackingHostValve.REQUEST_PROCESSED))).thenReturn(Boolean.TRUE);
    when(_request.getNote(eq(RequestTrackingHostValve.SESSION_ID_CHANGED)))
        .thenReturn(Boolean.FALSE);

    when(_sessionIdFormat.extractMemcachedId(anyString())).thenReturn(PRIMARY_NODE_IDENTIFIER);
    when(_service.getMemcachedNodesManager()).thenReturn(_memcachedNodesManager);
    when(_memcachedNodesManager.isNodeAvailable(PRIMARY_NODE_IDENTIFIER))
        .thenReturn(IS_PRIMARY_MEMCACHED_NODE_OPERATIONAL);
    when(_memcachedNodesManager.getSessionIdFormat()).thenReturn(_sessionIdFormat);
  }
  /**
   * Process Comet event.
   *
   * @param request Request to be processed
   * @param response Response to be produced
   * @param event the event
   * @exception IOException if an input/output error occurred
   * @exception ServletException if a servlet error occurred
   */
  @Override
  public final void event(Request request, Response response, CometEvent event)
      throws IOException, ServletException {

    // Select the Context to be used for this Request
    Context context = request.getContext();

    // Bind the context CL to the current thread
    if (context.getLoader() != null) {
      // Not started - it should check for availability first
      // This should eventually move to Engine, it's generic.
      Thread.currentThread().setContextClassLoader(context.getLoader().getClassLoader());
    }

    // Ask this Context to process this request
    context.getPipeline().getFirst().event(request, response, event);

    // Error page processing
    response.setSuspended(false);

    Throwable t = (Throwable) request.getAttribute(RequestDispatcher.ERROR_EXCEPTION);

    if (t != null) {
      throwable(request, response, t);
    } else {
      status(request, response);
    }

    // Access a session (if present) to update last accessed time, based on a
    // strict interpretation of the specification
    if (ACCESS_SESSION) {
      request.getSession(false);
    }

    // Restore the context classloader
    Thread.currentThread().setContextClassLoader(StandardHostValve.class.getClassLoader());
  }
 @Override
 public ApiResponse signOutAll() {
   ApiResponse response = ApiResponse.createDefaultApiResponse();
   HttpServletRequest request = HttpUtil.getRequest();
   HttpSession httpSession = HttpUtil.getSession();
   if (request instanceof RequestFacade) {
     Field requestField = null;
     try {
       requestField = request.getClass().getDeclaredField("request");
     } catch (NoSuchFieldException e) {
       e.printStackTrace();
     }
     if (requestField != null) {
       requestField.setAccessible(true);
       Request req = null;
       try {
         req = (Request) requestField.get(request);
       } catch (IllegalAccessException e) {
         e.printStackTrace();
       }
       if (req != null) {
         Context context = req.getContext();
         Manager manager = context.getManager();
         Session[] sessions = manager.findSessions();
         if (sessions != null) {
           for (Session session : sessions) {
             if (!httpSession.getId().equals(session.getId())) {
               session.expire();
             }
           }
         }
       }
     }
   }
   return response;
 }
 @Override
 public void addElement(
     StringBuilder buf, Date date, Request request, Response response, long time) {
   buf.append(wrap(request.getContext().getServletContext().getAttribute(attribute)));
 }
  /**
   * Handle the specified Throwable encountered while processing the specified Request to produce
   * the specified Response. Any exceptions that occur during generation of the exception report are
   * logged and swallowed.
   *
   * @param request The request being processed
   * @param response The response being generated
   * @param throwable The exception that occurred (which possibly wraps a root cause exception
   */
  protected void throwable(Request request, Response response, Throwable throwable) {
    Context context = request.getContext();
    if (context == null) return;

    Throwable realError = throwable;

    if (realError instanceof ServletException) {
      realError = ((ServletException) realError).getRootCause();
      if (realError == null) {
        realError = throwable;
      }
    }

    // If this is an aborted request from a client just log it and return
    if (realError instanceof ClientAbortException) {
      if (log.isDebugEnabled()) {
        log.debug(sm.getString("standardHost.clientAbort", realError.getCause().getMessage()));
      }
      return;
    }

    ErrorPage errorPage = findErrorPage(context, throwable);
    if ((errorPage == null) && (realError != throwable)) {
      errorPage = findErrorPage(context, realError);
    }

    if (errorPage != null) {
      if (response.setErrorReported()) {
        response.setAppCommitted(false);
        request.setAttribute(Globals.DISPATCHER_REQUEST_PATH_ATTR, errorPage.getLocation());
        request.setAttribute(Globals.DISPATCHER_TYPE_ATTR, DispatcherType.ERROR);
        request.setAttribute(
            RequestDispatcher.ERROR_STATUS_CODE,
            new Integer(HttpServletResponse.SC_INTERNAL_SERVER_ERROR));
        request.setAttribute(RequestDispatcher.ERROR_MESSAGE, throwable.getMessage());
        request.setAttribute(RequestDispatcher.ERROR_EXCEPTION, realError);
        Wrapper wrapper = request.getWrapper();
        if (wrapper != null)
          request.setAttribute(RequestDispatcher.ERROR_SERVLET_NAME, wrapper.getName());
        request.setAttribute(RequestDispatcher.ERROR_REQUEST_URI, request.getRequestURI());
        request.setAttribute(RequestDispatcher.ERROR_EXCEPTION_TYPE, realError.getClass());
        if (custom(request, response, errorPage)) {
          try {
            response.finishResponse();
          } catch (IOException e) {
            container.getLogger().warn("Exception Processing " + errorPage, e);
          }
        }
      }
    } else {
      // A custom error-page has not been defined for the exception
      // that was thrown during request processing. Check if an
      // error-page for error code 500 was specified and if so,
      // send that page back as the response.
      response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
      // The response is an error
      response.setError();

      status(request, response);
    }
  }
  /**
   * Select the appropriate child Context to process this request, based on the specified request
   * URI. If no matching Context can be found, return an appropriate HTTP error.
   *
   * @param request Request to be processed
   * @param response Response to be produced
   * @exception IOException if an input/output error occurred
   * @exception ServletException if a servlet error occurred
   */
  @Override
  public final void invoke(Request request, Response response)
      throws IOException, ServletException {

    /*
     * xujb:
     * 和Engine一样,调用下层的context,让它来做一些处理
     * 自身也处理了一些的逻辑
     *
     * */

    // Select the Context to be used for this Request
    Context context = request.getContext();
    if (context == null) {
      response.sendError(
          HttpServletResponse.SC_INTERNAL_SERVER_ERROR, sm.getString("standardHost.noContext"));
      return;
    }

    // Bind the context CL to the current thread
    if (context.getLoader() != null) {
      // Not started - it should check for availability first
      // This should eventually move to Engine, it's generic.
      if (Globals.IS_SECURITY_ENABLED) {
        PrivilegedAction<Void> pa = new PrivilegedSetTccl(context.getLoader().getClassLoader());
        AccessController.doPrivileged(pa);
      } else {
        Thread.currentThread().setContextClassLoader(context.getLoader().getClassLoader());
      }
    }
    if (request.isAsyncSupported()) {
      request.setAsyncSupported(context.getPipeline().isAsyncSupported());
    }

    boolean asyncAtStart = request.isAsync();
    boolean asyncDispatching = request.isAsyncDispatching();
    if (asyncAtStart || context.fireRequestInitEvent(request)) {

      // Ask this Context to process this request. Requests that are in
      // async mode and are not being dispatched to this resource must be
      // in error and have been routed here to check for application
      // defined error pages.
      try {
        if (!asyncAtStart || asyncDispatching) {
          context.getPipeline().getFirst().invoke(request, response);
        } else {
          // Make sure this request/response is here because an error
          // report is required.
          if (!response.isErrorReportRequired()) {
            throw new IllegalStateException(sm.getString("standardHost.asyncStateError"));
          }
        }
      } catch (Throwable t) {
        ExceptionUtils.handleThrowable(t);
        // If a new error occurred while trying to report a previous
        // error simply log the new error and allow the original error
        // to be reported.
        if (response.isErrorReportRequired()) {
          container.getLogger().error("Exception Processing " + request.getRequestURI(), t);
        } else {
          request.setAttribute(RequestDispatcher.ERROR_EXCEPTION, t);
          throwable(request, response, t);
        }
      }

      // Now that the request/response pair is back under container
      // control lift the suspension so that the error handling can
      // complete and/or the container can flush any remaining data
      response.setSuspended(false);

      Throwable t = (Throwable) request.getAttribute(RequestDispatcher.ERROR_EXCEPTION);

      // Protect against NPEs if the context was destroyed during a
      // long running request.
      if (!context.getState().isAvailable()) {
        return;
      }

      // Look for (and render if found) an application level error page
      if (response.isErrorReportRequired()) {
        if (t != null) {
          throwable(request, response, t);
        } else {
          status(request, response);
        }
      }

      if (!request.isAsync() && (!asyncAtStart || !response.isErrorReportRequired())) {
        context.fireRequestDestroyEvent(request);
      }
    }

    // Access a session (if present) to update last accessed time, based on a
    // strict interpretation of the specification
    if (ACCESS_SESSION) {
      request.getSession(false);
    }

    // Restore the context classloader
    if (Globals.IS_SECURITY_ENABLED) {
      PrivilegedAction<Void> pa = new PrivilegedSetTccl(StandardHostValve.class.getClassLoader());
      AccessController.doPrivileged(pa);
    } else {
      Thread.currentThread().setContextClassLoader(StandardHostValve.class.getClassLoader());
    }
  }
  /**
   * Enforce any user data constraint required by the security constraint guarding this request URI.
   * Return <code>true</code> if this constraint was not violated and processing should continue, or
   * <code>false</code> if we have created a response already.
   *
   * @param request Request we are processing
   * @param response Response we are creating
   * @param constraints Security constraint being checked
   * @exception IOException if an input/output error occurs
   */
  @Override
  public boolean hasUserDataPermission(
      Request request, Response response, SecurityConstraint[] constraints) throws IOException {

    // Is there a relevant user data constraint?
    if (constraints == null || constraints.length == 0) {
      if (log.isDebugEnabled()) log.debug("  No applicable security constraint defined");
      return (true);
    }
    for (int i = 0; i < constraints.length; i++) {
      SecurityConstraint constraint = constraints[i];
      String userConstraint = constraint.getUserConstraint();
      if (userConstraint == null) {
        if (log.isDebugEnabled()) log.debug("  No applicable user data constraint defined");
        return (true);
      }
      if (userConstraint.equals(Constants.NONE_TRANSPORT)) {
        if (log.isDebugEnabled()) log.debug("  User data constraint has no restrictions");
        return (true);
      }
    }
    // Validate the request against the user data constraint
    if (request.getRequest().isSecure()) {
      if (log.isDebugEnabled()) log.debug("  User data constraint already satisfied");
      return (true);
    }
    // Initialize variables we need to determine the appropriate action
    int redirectPort = request.getConnector().getRedirectPort();

    // Is redirecting disabled?
    if (redirectPort <= 0) {
      if (log.isDebugEnabled()) log.debug("  SSL redirect is disabled");
      response.sendError(HttpServletResponse.SC_FORBIDDEN, request.getRequestURI());
      return (false);
    }

    // Redirect to the corresponding SSL port
    StringBuilder file = new StringBuilder();
    String protocol = "https";
    String host = request.getServerName();
    // Protocol
    file.append(protocol).append("://").append(host);
    // Host with port
    if (redirectPort != 443) {
      file.append(":").append(redirectPort);
    }
    // URI
    file.append(request.getRequestURI());
    String requestedSessionId = request.getRequestedSessionId();
    if ((requestedSessionId != null) && request.isRequestedSessionIdFromURL()) {
      file.append(";");
      file.append(SessionConfig.getSessionUriParamName(request.getContext()));
      file.append("=");
      file.append(requestedSessionId);
    }
    String queryString = request.getQueryString();
    if (queryString != null) {
      file.append('?');
      file.append(queryString);
    }
    if (log.isDebugEnabled()) log.debug("  Redirecting to " + file.toString());
    response.sendRedirect(file.toString());
    return (false);
  }
  /**
   * Perform access control based on the specified authorization constraint. Return <code>true
   * </code> if this constraint is satisfied and processing should continue, or <code>false</code>
   * otherwise.
   *
   * @param request Request we are processing
   * @param response Response we are creating
   * @param constraints Security constraint we are enforcing
   * @param context The Context to which client of this class is attached.
   * @exception IOException if an input/output error occurs
   */
  @Override
  public boolean hasResourcePermission(
      Request request, Response response, SecurityConstraint[] constraints, Context context)
      throws IOException {

    if (constraints == null || constraints.length == 0) return (true);

    // Specifically allow access to the form login and form error pages
    // and the "j_security_check" action
    LoginConfig config = context.getLoginConfig();
    if ((config != null) && (Constants.FORM_METHOD.equals(config.getAuthMethod()))) {
      String requestURI = request.getRequestPathMB().toString();
      String loginPage = config.getLoginPage();
      if (loginPage.equals(requestURI)) {
        if (log.isDebugEnabled()) log.debug(" Allow access to login page " + loginPage);
        return (true);
      }
      String errorPage = config.getErrorPage();
      if (errorPage.equals(requestURI)) {
        if (log.isDebugEnabled()) log.debug(" Allow access to error page " + errorPage);
        return (true);
      }
      if (requestURI.endsWith(Constants.FORM_ACTION)) {
        if (log.isDebugEnabled()) log.debug(" Allow access to username/password submission");
        return (true);
      }
    }

    // Which user principal have we already authenticated?
    Principal principal = request.getPrincipal();
    boolean status = false;
    boolean denyfromall = false;
    for (int i = 0; i < constraints.length; i++) {
      SecurityConstraint constraint = constraints[i];

      String roles[];
      if (constraint.getAllRoles()) {
        // * means all roles defined in web.xml
        roles = request.getContext().findSecurityRoles();
      } else {
        roles = constraint.findAuthRoles();
      }

      if (roles == null) roles = new String[0];

      if (log.isDebugEnabled()) log.debug("  Checking roles " + principal);

      if (roles.length == 0 && !constraint.getAllRoles()) {
        if (constraint.getAuthConstraint()) {
          if (log.isDebugEnabled()) log.debug("No roles");
          status = false; // No listed roles means no access at all
          denyfromall = true;
          break;
        }

        if (log.isDebugEnabled()) log.debug("Passing all access");
        status = true;
      } else if (principal == null) {
        if (log.isDebugEnabled()) log.debug("  No user authenticated, cannot grant access");
      } else {
        for (int j = 0; j < roles.length; j++) {
          if (hasRole(null, principal, roles[j])) {
            status = true;
            if (log.isDebugEnabled()) log.debug("Role found:  " + roles[j]);
          } else if (log.isDebugEnabled()) log.debug("No role found:  " + roles[j]);
        }
      }
    }

    if (!denyfromall && allRolesMode != AllRolesMode.STRICT_MODE && !status && principal != null) {
      if (log.isDebugEnabled()) {
        log.debug("Checking for all roles mode: " + allRolesMode);
      }
      // Check for an all roles(role-name="*")
      for (int i = 0; i < constraints.length; i++) {
        SecurityConstraint constraint = constraints[i];
        String roles[];
        // If the all roles mode exists, sets
        if (constraint.getAllRoles()) {
          if (allRolesMode == AllRolesMode.AUTH_ONLY_MODE) {
            if (log.isDebugEnabled()) {
              log.debug("Granting access for role-name=*, auth-only");
            }
            status = true;
            break;
          }

          // For AllRolesMode.STRICT_AUTH_ONLY_MODE there must be zero roles
          roles = request.getContext().findSecurityRoles();
          if (roles.length == 0 && allRolesMode == AllRolesMode.STRICT_AUTH_ONLY_MODE) {
            if (log.isDebugEnabled()) {
              log.debug("Granting access for role-name=*, strict auth-only");
            }
            status = true;
            break;
          }
        }
      }
    }

    // Return a "Forbidden" message denying access to this resource
    if (!status) {
      response.sendError(HttpServletResponse.SC_FORBIDDEN, sm.getString("realmBase.forbidden"));
    }
    return status;
  }
Пример #15
0
  private void doInvoke(Request request, Response response, boolean chaining)
      throws IOException, ServletException {

    if ((valves.length > 0) || (basic != null)) {
      // Set the status so that if there are no valves (other than the
      // basic one), the basic valve's request processing logic will
      // be invoked
      int status = GlassFishValve.INVOKE_NEXT;

      // Iterate over all the valves in the pipeline and invoke
      // each valve's processing logic and then move onto to the
      // next valve in the pipeline only if the previous valve indicated
      // that the pipeline should proceed.
      int i;
      for (i = 0; i < valves.length; i++) {
        Request req = request;
        Response resp = response;
        if (chaining) {
          req = getRequest(request);
          resp = getResponse(request, response);
        }
        status = valves[i].invoke(req, resp);
        if (status != GlassFishValve.INVOKE_NEXT) break;
      }

      // Save a reference to the valve[], to ensure that postInvoke()
      // is invoked on the original valve[], in case a valve gets added
      // or removed during the invocation of the basic valve (e.g.,
      // in case access logging is enabled or disabled by some kind of
      // admin servlet), in which case the indices used for postInvoke
      // invocations below would be off
      GlassFishValve[] savedValves = valves;

      // Invoke the basic valve's request processing and post-request
      // logic only if the pipeline was not aborted (i.e. no valve
      // returned END_PIPELINE).
      // In addition, the basic valve needs to be invoked by the
      // pipeline only if no Tomcat-style valves have been added.
      // Otherwise, it will be invoked by the last Tomcat-style valve
      // directly.
      if (status == GlassFishValve.INVOKE_NEXT) {
        if (firstTcValve != null) {
          firstTcValve.invoke(
              (org.apache.catalina.connector.Request) request,
              (org.apache.catalina.connector.Response) response);
        } else if (basic != null) {
          Request req = request;
          Response resp = response;
          if (chaining) {
            req = getRequest(request);
            resp = getResponse(request, response);
          }
          basic.invoke(req, resp);
          basic.postInvoke(req, resp);
        }
      }

      // Invoke the post-request processing logic only on those valves
      // that returned a status of INVOKE_NEXT
      for (int j = i - 1; j >= 0; j--) {
        Request req = request;
        Response resp = response;
        if (chaining) {
          req = getRequest(request);
          resp = getResponse(request, response);
        }

        savedValves[j].postInvoke(req, resp);
      }

      savedValves = null;

    } else {
      throw new ServletException(rb.getString(NO_VALVES_IN_PIPELINE_EXCEPTION));
    }

    // Calls the protocol handler's init method if the request is marked to be upgraded
    if (request instanceof org.apache.catalina.connector.Request) {
      org.apache.catalina.connector.Request req = (org.apache.catalina.connector.Request) request;
      if (req.isUpgrade()) {
        HttpUpgradeHandler handler = req.getHttpUpgradeHandler();
        if (handler != null) {
          WebConnectionImpl wc =
              new WebConnectionImpl(
                  req.getInputStream(),
                  ((org.apache.catalina.connector.Response) req.getResponse()).getOutputStream());
          wc.setRequest(req);
          req.setWebConnection(wc);
          if (response instanceof org.apache.catalina.connector.Response) {
            wc.setResponse((org.apache.catalina.connector.Response) response);
          }
          Context context = req.getContext();
          try {
            context.fireContainerEvent(ContainerEvent.BEFORE_UPGRADE_HANDLER_INITIALIZED, handler);
            handler.init(wc);
          } finally {
            context.fireContainerEvent(ContainerEvent.AFTER_UPGRADE_HANDLER_INITIALIZED, handler);
          }
        } else {
          log.log(Level.SEVERE, PROTOCOL_HANDLER_REQUIRED_EXCEPTION);
        }
        req.setUpgrade(false);
      }
    }
  }
    public boolean validate(Request request) {
      if ((userName == null)
          || (realmName == null)
          || (nonce == null)
          || (uri == null)
          || (response == null)) {
        return false;
      }

      // Validate the URI - should match the request line sent by client
      if (validateUri) {
        String uriQuery;
        String query = request.getQueryString();
        if (query == null) {
          uriQuery = request.getRequestURI();
        } else {
          uriQuery = request.getRequestURI() + "?" + query;
        }
        if (!uri.equals(uriQuery)) {
          // Some clients (older Android) use an absolute URI for
          // DIGEST but a relative URI in the request line.
          // request. 2.3.5 < fixed Android version <= 4.0.3
          String host = request.getHeader("host");
          String scheme = request.getScheme();
          if (host != null && !uriQuery.startsWith(scheme)) {
            StringBuilder absolute = new StringBuilder();
            absolute.append(scheme);
            absolute.append("://");
            absolute.append(host);
            absolute.append(uriQuery);
            if (!uri.equals(absolute.toString())) {
              return false;
            }
          } else {
            return false;
          }
        }
      }

      // Validate the Realm name
      String lcRealm = getRealmName(request.getContext());
      if (!lcRealm.equals(realmName)) {
        return false;
      }

      // Validate the opaque string
      if (!opaque.equals(opaqueReceived)) {
        return false;
      }

      // Validate nonce
      int i = nonce.indexOf(":");
      if (i < 0 || (i + 1) == nonce.length()) {
        return false;
      }
      long nonceTime;
      try {
        nonceTime = Long.parseLong(nonce.substring(0, i));
      } catch (NumberFormatException nfe) {
        return false;
      }
      String md5clientIpTimeKey = nonce.substring(i + 1);
      long currentTime = System.currentTimeMillis();
      if ((currentTime - nonceTime) > nonceValidity) {
        nonceStale = true;
        synchronized (nonces) {
          nonces.remove(nonce);
        }
      }
      String serverIpTimeKey = request.getRemoteAddr() + ":" + nonceTime + ":" + key;
      byte[] buffer =
          ConcurrentMessageDigest.digestMD5(serverIpTimeKey.getBytes(StandardCharsets.ISO_8859_1));
      String md5ServerIpTimeKey = MD5Encoder.encode(buffer);
      if (!md5ServerIpTimeKey.equals(md5clientIpTimeKey)) {
        return false;
      }

      // Validate qop
      if (qop != null && !QOP.equals(qop)) {
        return false;
      }

      // Validate cnonce and nc
      // Check if presence of nc and Cnonce is consistent with presence of qop
      if (qop == null) {
        if (cnonce != null || nc != null) {
          return false;
        }
      } else {
        if (cnonce == null || nc == null) {
          return false;
        }
        // RFC 2617 says nc must be 8 digits long. Older Android clients
        // use 6. 2.3.5 < fixed Android version <= 4.0.3
        if (nc.length() < 6 || nc.length() > 8) {
          return false;
        }
        long count;
        try {
          count = Long.parseLong(nc, 16);
        } catch (NumberFormatException nfe) {
          return false;
        }
        NonceInfo info;
        synchronized (nonces) {
          info = nonces.get(nonce);
        }
        if (info == null) {
          // Nonce is valid but not in cache. It must have dropped out
          // of the cache - force a re-authentication
          nonceStale = true;
        } else {
          if (!info.nonceCountValid(count)) {
            return false;
          }
        }
      }
      return true;
    }