Search in sources :

Example 46 with MessageBytes

use of org.apache.tomcat.util.buf.MessageBytes in project tomcat70 by apache.

the class StandardContextValve method invoke.

/**
 * Select the appropriate child Wrapper to process this request,
 * based on the specified request URI.  If no matching Wrapper 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 {
    // Disallow any direct access to resources under WEB-INF or META-INF
    MessageBytes requestPathMB = request.getRequestPathMB();
    if ((requestPathMB.startsWithIgnoreCase("/META-INF/", 0)) || (requestPathMB.equalsIgnoreCase("/META-INF")) || (requestPathMB.startsWithIgnoreCase("/WEB-INF/", 0)) || (requestPathMB.equalsIgnoreCase("/WEB-INF"))) {
        response.sendError(HttpServletResponse.SC_NOT_FOUND);
        return;
    }
    // Select the Wrapper to be used for this Request
    Wrapper wrapper = request.getWrapper();
    if (wrapper == null || wrapper.isUnavailable()) {
        response.sendError(HttpServletResponse.SC_NOT_FOUND);
        return;
    }
    // Acknowledge the request
    try {
        response.sendAcknowledgement();
    } catch (IOException ioe) {
        container.getLogger().error(sm.getString("standardContextValve.acknowledgeException"), ioe);
        request.setAttribute(RequestDispatcher.ERROR_EXCEPTION, ioe);
        response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
        return;
    }
    if (request.isAsyncSupported()) {
        request.setAsyncSupported(wrapper.getPipeline().isAsyncSupported());
    }
    wrapper.getPipeline().getFirst().invoke(request, response);
}
Also used : Wrapper(org.apache.catalina.Wrapper) MessageBytes(org.apache.tomcat.util.buf.MessageBytes) IOException(java.io.IOException)

Example 47 with MessageBytes

use of org.apache.tomcat.util.buf.MessageBytes in project tomcat70 by apache.

the class ApplicationContext method getRequestDispatcher.

/**
 * Return a <code>RequestDispatcher</code> instance that acts as a
 * wrapper for the resource at the given path.  The path must begin
 * with a "/" and is interpreted as relative to the current context root.
 *
 * @param path The path to the desired resource.
 */
@Override
public RequestDispatcher getRequestDispatcher(final String path) {
    // Validate the path argument
    if (path == null) {
        return (null);
    }
    if (!path.startsWith("/")) {
        throw new IllegalArgumentException(sm.getString("applicationContext.requestDispatcher.iae", path));
    }
    // Need to separate the query string and the uri. This is required for
    // the ApplicationDispatcher constructor. Mapping also requires the uri
    // without the query string.
    String uri;
    String queryString;
    int pos = path.indexOf('?');
    if (pos >= 0) {
        uri = path.substring(0, pos);
        queryString = path.substring(pos + 1);
    } else {
        uri = path;
        queryString = null;
    }
    String normalizedPath = RequestUtil.normalize(uri);
    if (normalizedPath == null) {
        return (null);
    }
    if (getContext().getDispatchersUseEncodedPaths()) {
        // Decode
        String decodedPath;
        try {
            decodedPath = URLDecoder.decode(normalizedPath, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            // Impossible
            return null;
        }
        // Security check to catch attempts to encode /../ sequences
        normalizedPath = RequestUtil.normalize(decodedPath);
        if (!decodedPath.equals(normalizedPath)) {
            getContext().getLogger().warn(sm.getString("applicationContext.illegalDispatchPath", path), new IllegalArgumentException());
            return null;
        }
        // URI needs to include the context path
        uri = URLEncoder.DEFAULT.encode(getContextPath(), "UTF-8") + uri;
    } else {
        // uri is passed to the constructor for ApplicationDispatcher and is
        // ultimately used as the value for getRequestURI() which returns
        // encoded values. Therefore, since the value passed in for path
        // was decoded, encode uri here.
        uri = URLEncoder.DEFAULT.encode(getContextPath() + uri, "UTF-8");
    }
    pos = normalizedPath.length();
    // Use the thread local URI and mapping data
    DispatchData dd = dispatchData.get();
    if (dd == null) {
        dd = new DispatchData();
        dispatchData.set(dd);
    }
    MessageBytes uriMB = dd.uriMB;
    uriMB.recycle();
    // Use the thread local mapping data
    MappingData mappingData = dd.mappingData;
    // Map the URI
    CharChunk uriCC = uriMB.getCharChunk();
    try {
        uriCC.append(context.getPath(), 0, context.getPath().length());
        /*
             * Ignore any trailing path params (separated by ';') for mapping
             * purposes
             */
        int semicolon = normalizedPath.indexOf(';');
        if (pos >= 0 && semicolon > pos) {
            semicolon = -1;
        }
        uriCC.append(normalizedPath, 0, semicolon > 0 ? semicolon : pos);
        context.getMapper().map(uriMB, mappingData);
        if (mappingData.wrapper == null) {
            return (null);
        }
        /*
             * Append any trailing path params (separated by ';') that were
             * ignored for mapping purposes, so that they're reflected in the
             * RequestDispatcher's requestURI
             */
        if (semicolon > 0) {
            uriCC.append(normalizedPath, semicolon, pos - semicolon);
        }
    } catch (Exception e) {
        // Should never happen
        log(sm.getString("applicationContext.mapping.error"), e);
        return (null);
    }
    Wrapper wrapper = (Wrapper) mappingData.wrapper;
    String wrapperPath = mappingData.wrapperPath.toString();
    String pathInfo = mappingData.pathInfo.toString();
    mappingData.recycle();
    // Construct a RequestDispatcher to process this request
    return new ApplicationDispatcher(wrapper, uri, wrapperPath, pathInfo, queryString, null);
}
Also used : Wrapper(org.apache.catalina.Wrapper) UnsupportedEncodingException(java.io.UnsupportedEncodingException) MessageBytes(org.apache.tomcat.util.buf.MessageBytes) MappingData(org.apache.tomcat.util.http.mapper.MappingData) CharChunk(org.apache.tomcat.util.buf.CharChunk) ServletException(javax.servlet.ServletException) NamingException(javax.naming.NamingException) InvocationTargetException(java.lang.reflect.InvocationTargetException) UnsupportedEncodingException(java.io.UnsupportedEncodingException) MalformedURLException(java.net.MalformedURLException)

Example 48 with MessageBytes

use of org.apache.tomcat.util.buf.MessageBytes in project tomcat70 by apache.

the class BasicAuthenticator method authenticate.

@Override
public boolean authenticate(Request request, HttpServletResponse response, LoginConfig config) throws IOException {
    if (checkForCachedAuthentication(request, response, true)) {
        return true;
    }
    // Validate any credentials already included with this request
    String username = null;
    String password = null;
    MessageBytes authorization = request.getCoyoteRequest().getMimeHeaders().getValue("authorization");
    if (authorization != null) {
        authorization.toBytes();
        ByteChunk authorizationBC = authorization.getByteChunk();
        if (authorizationBC.startsWithIgnoreCase("basic ", 0)) {
            authorizationBC.setOffset(authorizationBC.getOffset() + 6);
            byte[] decoded = Base64.decodeBase64(authorizationBC.getBuffer(), authorizationBC.getOffset(), authorizationBC.getLength());
            // Get username and password
            int colon = -1;
            for (int i = 0; i < decoded.length; i++) {
                if (decoded[i] == ':') {
                    colon = i;
                    break;
                }
            }
            if (colon < 0) {
                username = new String(decoded, charset);
            } else {
                username = new String(decoded, 0, colon, charset);
                password = new String(decoded, colon + 1, decoded.length - colon - 1, charset);
            }
            authorizationBC.setOffset(authorizationBC.getOffset() - 6);
        }
        Principal principal = context.getRealm().authenticate(username, password);
        if (principal != null) {
            register(request, response, principal, HttpServletRequest.BASIC_AUTH, username, password);
            return (true);
        }
    }
    StringBuilder value = new StringBuilder(16);
    value.append("Basic realm=\"");
    if (config.getRealmName() == null) {
        value.append(REALM_NAME);
    } else {
        value.append(config.getRealmName());
    }
    value.append('\"');
    if (charsetString != null && !charsetString.isEmpty()) {
        value.append(", charset=");
        value.append(charsetString);
    }
    response.setHeader(AUTH_HEADER_NAME, value.toString());
    response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
    return (false);
}
Also used : ByteChunk(org.apache.tomcat.util.buf.ByteChunk) MessageBytes(org.apache.tomcat.util.buf.MessageBytes) Principal(java.security.Principal)

Example 49 with MessageBytes

use of org.apache.tomcat.util.buf.MessageBytes in project tomcat70 by apache.

the class FormAuthenticator method authenticate.

// --------------------------------------------------------- Public Methods
/**
 * Authenticate the user making this request, based on the specified
 * login configuration.  Return <code>true</code> if any specified
 * constraint has been satisfied, or <code>false</code> if we have
 * created a response challenge already.
 *
 * @param request Request we are processing
 * @param response Response we are creating
 * @param config    Login configuration describing how authentication
 *              should be performed
 *
 * @exception IOException if an input/output error occurs
 */
@Override
public boolean authenticate(Request request, HttpServletResponse response, LoginConfig config) throws IOException {
    if (checkForCachedAuthentication(request, response, true)) {
        return (true);
    }
    // References to objects we will need later
    Session session = null;
    Principal principal = null;
    // Have we authenticated this user before but have caching disabled?
    if (!cache) {
        session = request.getSessionInternal(true);
        if (log.isDebugEnabled()) {
            log.debug("Checking for reauthenticate in session " + session);
        }
        String username = (String) session.getNote(Constants.SESS_USERNAME_NOTE);
        String password = (String) session.getNote(Constants.SESS_PASSWORD_NOTE);
        if ((username != null) && (password != null)) {
            if (log.isDebugEnabled()) {
                log.debug("Reauthenticating username '" + username + "'");
            }
            principal = context.getRealm().authenticate(username, password);
            if (principal != null) {
                session.setNote(Constants.FORM_PRINCIPAL_NOTE, principal);
                if (!matchRequest(request)) {
                    register(request, response, principal, HttpServletRequest.FORM_AUTH, username, password);
                    return (true);
                }
            }
            if (log.isDebugEnabled()) {
                log.debug("Reauthentication failed, proceed normally");
            }
        }
    }
    // authentication?  If so, forward the *original* request instead.
    if (matchRequest(request)) {
        session = request.getSessionInternal(true);
        if (log.isDebugEnabled()) {
            log.debug("Restore request from session '" + session.getIdInternal() + "'");
        }
        principal = (Principal) session.getNote(Constants.FORM_PRINCIPAL_NOTE);
        register(request, response, principal, HttpServletRequest.FORM_AUTH, (String) session.getNote(Constants.SESS_USERNAME_NOTE), (String) session.getNote(Constants.SESS_PASSWORD_NOTE));
        // and password in the session, so remove them
        if (cache) {
            session.removeNote(Constants.SESS_USERNAME_NOTE);
            session.removeNote(Constants.SESS_PASSWORD_NOTE);
        }
        if (restoreRequest(request, session)) {
            if (log.isDebugEnabled()) {
                log.debug("Proceed to restored request");
            }
            return (true);
        } else {
            if (log.isDebugEnabled()) {
                log.debug("Restore of original request failed");
            }
            response.sendError(HttpServletResponse.SC_BAD_REQUEST);
            return (false);
        }
    }
    // Acquire references to objects we will need to evaluate
    MessageBytes uriMB = MessageBytes.newInstance();
    CharChunk uriCC = uriMB.getCharChunk();
    uriCC.setLimit(-1);
    String contextPath = request.getContextPath();
    String requestURI = request.getDecodedRequestURI();
    // Is this the action request from the login page?
    boolean loginAction = requestURI.startsWith(contextPath) && requestURI.endsWith(Constants.FORM_ACTION);
    // No -- Save this request and redirect to the form login page
    if (!loginAction) {
        // may not go to the correct web application
        if (request.getServletPath().length() == 0 && request.getPathInfo() == null) {
            StringBuilder location = new StringBuilder(requestURI);
            location.append('/');
            if (request.getQueryString() != null) {
                location.append('?');
                location.append(request.getQueryString());
            }
            response.sendRedirect(response.encodeRedirectURL(location.toString()));
            return false;
        }
        session = request.getSessionInternal(true);
        if (log.isDebugEnabled()) {
            log.debug("Save request in session '" + session.getIdInternal() + "'");
        }
        try {
            saveRequest(request, session);
        } catch (IOException ioe) {
            log.debug("Request body too big to save during authentication");
            response.sendError(HttpServletResponse.SC_FORBIDDEN, sm.getString("authenticator.requestBodyTooBig"));
            return (false);
        }
        forwardToLoginPage(request, response, config);
        return (false);
    }
    // Yes -- Acknowledge the request, validate the specified credentials
    // and redirect to the error page if they are not correct
    request.getResponse().sendAcknowledgement();
    Realm realm = context.getRealm();
    if (characterEncoding != null) {
        request.setCharacterEncoding(characterEncoding);
    }
    String username = request.getParameter(Constants.FORM_USERNAME);
    String password = request.getParameter(Constants.FORM_PASSWORD);
    if (log.isDebugEnabled()) {
        log.debug("Authenticating username '" + username + "'");
    }
    principal = realm.authenticate(username, password);
    if (principal == null) {
        forwardToErrorPage(request, response, config);
        return (false);
    }
    if (log.isDebugEnabled()) {
        log.debug("Authentication of '" + username + "' was successful");
    }
    if (session == null) {
        session = request.getSessionInternal(false);
    }
    if (session == null) {
        if (containerLog.isDebugEnabled()) {
            containerLog.debug("User took so long to log on the session expired");
        }
        if (landingPage == null) {
            response.sendError(HttpServletResponse.SC_REQUEST_TIMEOUT, sm.getString("authenticator.sessionExpired"));
        } else {
            // Make the authenticator think the user originally requested
            // the landing page
            String uri = request.getContextPath() + landingPage;
            SavedRequest saved = new SavedRequest();
            saved.setMethod("GET");
            saved.setRequestURI(uri);
            saved.setDecodedRequestURI(uri);
            request.getSessionInternal(true).setNote(Constants.FORM_REQUEST_NOTE, saved);
            response.sendRedirect(response.encodeRedirectURL(uri));
        }
        return (false);
    }
    // Save the authenticated Principal in our session
    session.setNote(Constants.FORM_PRINCIPAL_NOTE, principal);
    // Save the username and password as well
    session.setNote(Constants.SESS_USERNAME_NOTE, username);
    session.setNote(Constants.SESS_PASSWORD_NOTE, password);
    // Redirect the user to the original request URI (which will cause
    // the original request to be restored)
    requestURI = savedRequestURL(session);
    if (log.isDebugEnabled()) {
        log.debug("Redirecting to original '" + requestURI + "'");
    }
    if (requestURI == null) {
        if (landingPage == null) {
            response.sendError(HttpServletResponse.SC_BAD_REQUEST, sm.getString("authenticator.formlogin"));
        } else {
            // Make the authenticator think the user originally requested
            // the landing page
            String uri = request.getContextPath() + landingPage;
            SavedRequest saved = new SavedRequest();
            saved.setMethod("GET");
            saved.setRequestURI(uri);
            saved.setDecodedRequestURI(uri);
            session.setNote(Constants.FORM_REQUEST_NOTE, saved);
            response.sendRedirect(response.encodeRedirectURL(uri));
        }
    } else {
        response.sendRedirect(response.encodeRedirectURL(requestURI));
    }
    return (false);
}
Also used : MessageBytes(org.apache.tomcat.util.buf.MessageBytes) IOException(java.io.IOException) Realm(org.apache.catalina.Realm) Principal(java.security.Principal) CharChunk(org.apache.tomcat.util.buf.CharChunk) Session(org.apache.catalina.Session)

Example 50 with MessageBytes

use of org.apache.tomcat.util.buf.MessageBytes in project tomcat70 by apache.

the class FormAuthenticator method restoreRequest.

/**
 * Restore the original request from information stored in our session.
 * If the original request is no longer present (because the session
 * timed out), return <code>false</code>; otherwise, return
 * <code>true</code>.
 *
 * @param request The request to be restored
 * @param session The session containing the saved information
 */
protected boolean restoreRequest(Request request, Session session) throws IOException {
    // Retrieve and remove the SavedRequest object from our session
    SavedRequest saved = (SavedRequest) session.getNote(Constants.FORM_REQUEST_NOTE);
    session.removeNote(Constants.FORM_REQUEST_NOTE);
    session.removeNote(Constants.FORM_PRINCIPAL_NOTE);
    if (saved == null) {
        return (false);
    }
    // Swallow any request body since we will be replacing it
    // Need to do this before headers are restored as AJP connector uses
    // content length header to determine how much data needs to be read for
    // request body
    byte[] buffer = new byte[4096];
    InputStream is = request.createInputStream();
    while (is.read(buffer) >= 0) {
    // Ignore request body
    }
    // Modify our current request to reflect the original one
    request.clearCookies();
    Iterator<Cookie> cookies = saved.getCookies();
    while (cookies.hasNext()) {
        request.addCookie(cookies.next());
    }
    String method = saved.getMethod();
    MimeHeaders rmh = request.getCoyoteRequest().getMimeHeaders();
    rmh.recycle();
    boolean cacheable = "GET".equalsIgnoreCase(method) || "HEAD".equalsIgnoreCase(method);
    Iterator<String> names = saved.getHeaderNames();
    while (names.hasNext()) {
        String name = names.next();
        // BZ 43687
        if (!("If-Modified-Since".equalsIgnoreCase(name) || (cacheable && "If-None-Match".equalsIgnoreCase(name)))) {
            Iterator<String> values = saved.getHeaderValues(name);
            while (values.hasNext()) {
                rmh.addValue(name).setString(values.next());
            }
        }
    }
    request.clearLocales();
    Iterator<Locale> locales = saved.getLocales();
    while (locales.hasNext()) {
        request.addLocale(locales.next());
    }
    request.getCoyoteRequest().getParameters().recycle();
    request.getCoyoteRequest().getParameters().setQueryStringEncoding(request.getConnector().getURIEncoding());
    ByteChunk body = saved.getBody();
    if (body != null) {
        request.getCoyoteRequest().action(ActionCode.REQ_SET_BODY_REPLAY, body);
        // Set content type
        MessageBytes contentType = MessageBytes.newInstance();
        // If no content type specified, use default for POST
        String savedContentType = saved.getContentType();
        if (savedContentType == null && "POST".equalsIgnoreCase(method)) {
            savedContentType = "application/x-www-form-urlencoded";
        }
        contentType.setString(savedContentType);
        request.getCoyoteRequest().setContentType(contentType);
    }
    request.getCoyoteRequest().method().setString(method);
    request.getCoyoteRequest().queryString().setString(saved.getQueryString());
    request.getCoyoteRequest().requestURI().setString(saved.getRequestURI());
    return (true);
}
Also used : Cookie(javax.servlet.http.Cookie) Locale(java.util.Locale) ByteChunk(org.apache.tomcat.util.buf.ByteChunk) InputStream(java.io.InputStream) MessageBytes(org.apache.tomcat.util.buf.MessageBytes) MimeHeaders(org.apache.tomcat.util.http.MimeHeaders)

Aggregations

MessageBytes (org.apache.tomcat.util.buf.MessageBytes)73 MimeHeaders (org.apache.tomcat.util.http.MimeHeaders)15 ByteChunk (org.apache.tomcat.util.buf.ByteChunk)14 IOException (java.io.IOException)11 Test (org.junit.Test)11 Context (org.apache.catalina.Context)10 LoggingBaseTest (org.apache.catalina.startup.LoggingBaseTest)8 Pattern (java.util.regex.Pattern)6 AbstractEndpoint (org.apache.tomcat.util.net.AbstractEndpoint)6 Principal (java.security.Principal)5 Wrapper (org.apache.catalina.Wrapper)5 CharChunk (org.apache.tomcat.util.buf.CharChunk)5 Host (org.apache.catalina.Host)4 ServletException (jakarta.servlet.ServletException)3 Cookie (jakarta.servlet.http.Cookie)3 UnsupportedEncodingException (java.io.UnsupportedEncodingException)3 HashSet (java.util.HashSet)3 ServletException (javax.servlet.ServletException)3 Cookie (javax.servlet.http.Cookie)3 Container (org.apache.catalina.Container)3