use of org.apache.tomcat.util.buf.MessageBytes in project tomcat by apache.
the class ChunkedInputFilter method parseHeader.
private boolean parseHeader() throws IOException {
MimeHeaders headers = request.getMimeHeaders();
byte chr = 0;
// Read new bytes if needed
if (readChunk == null || readChunk.position() >= readChunk.limit()) {
if (readBytes() < 0) {
throwEOFException(sm.getString("chunkedInputFilter.eosTrailer"));
}
}
// readBytes() above will set readChunk unless it returns a value < 0
chr = readChunk.get(readChunk.position());
// CRLF terminates the request
if (chr == Constants.CR || chr == Constants.LF) {
parseCRLF(false);
return false;
}
// Mark the current buffer position
int startPos = trailingHeaders.getEnd();
//
// Reading the header name
// Header name is always US-ASCII
//
boolean colon = false;
while (!colon) {
// Read new bytes if needed
if (readChunk == null || readChunk.position() >= readChunk.limit()) {
if (readBytes() < 0) {
throwEOFException(sm.getString("chunkedInputFilter.eosTrailer"));
}
}
// readBytes() above will set readChunk unless it returns a value < 0
chr = readChunk.get(readChunk.position());
if ((chr >= Constants.A) && (chr <= Constants.Z)) {
chr = (byte) (chr - Constants.LC_OFFSET);
}
if (chr == Constants.COLON) {
colon = true;
} else {
trailingHeaders.append(chr);
}
readChunk.position(readChunk.position() + 1);
}
int colonPos = trailingHeaders.getEnd();
//
// Reading the header value (which can be spanned over multiple lines)
//
boolean eol = false;
boolean validLine = true;
int lastSignificantChar = 0;
while (validLine) {
boolean space = true;
// Skipping spaces
while (space) {
// Read new bytes if needed
if (readChunk == null || readChunk.position() >= readChunk.limit()) {
if (readBytes() < 0) {
throwEOFException(sm.getString("chunkedInputFilter.eosTrailer"));
}
}
chr = readChunk.get(readChunk.position());
if ((chr == Constants.SP) || (chr == Constants.HT)) {
readChunk.position(readChunk.position() + 1);
// If we swallow whitespace, make sure it counts towards the
// limit placed on trailing header size
int newlimit = trailingHeaders.getLimit() - 1;
if (trailingHeaders.getEnd() > newlimit) {
throwIOException(sm.getString("chunkedInputFilter.maxTrailer"));
}
trailingHeaders.setLimit(newlimit);
} else {
space = false;
}
}
// Reading bytes until the end of the line
while (!eol) {
// Read new bytes if needed
if (readChunk == null || readChunk.position() >= readChunk.limit()) {
if (readBytes() < 0) {
throwEOFException(sm.getString("chunkedInputFilter.eosTrailer"));
}
}
chr = readChunk.get(readChunk.position());
if (chr == Constants.CR || chr == Constants.LF) {
parseCRLF(true);
eol = true;
} else if (chr == Constants.SP) {
trailingHeaders.append(chr);
} else {
trailingHeaders.append(chr);
lastSignificantChar = trailingHeaders.getEnd();
}
if (!eol) {
readChunk.position(readChunk.position() + 1);
}
}
// Read new bytes if needed
if (readChunk == null || readChunk.position() >= readChunk.limit()) {
if (readBytes() < 0) {
throwEOFException(sm.getString("chunkedInputFilter.eosTrailer"));
}
}
chr = readChunk.get(readChunk.position());
if ((chr != Constants.SP) && (chr != Constants.HT)) {
validLine = false;
} else {
eol = false;
// Copying one extra space in the buffer (since there must
// be at least one space inserted between the lines)
trailingHeaders.append(chr);
}
}
String headerName = new String(trailingHeaders.getBytes(), startPos, colonPos - startPos, StandardCharsets.ISO_8859_1);
if (allowedTrailerHeaders.contains(headerName.toLowerCase(Locale.ENGLISH))) {
MessageBytes headerValue = headers.addValue(headerName);
// Set the header value
headerValue.setBytes(trailingHeaders.getBytes(), colonPos, lastSignificantChar - colonPos);
}
return true;
}
use of org.apache.tomcat.util.buf.MessageBytes in project tomcat by apache.
the class TestCoyoteAdapter method doTestNormalize.
private void doTestNormalize(String input, String expected) {
MessageBytes mb = MessageBytes.newInstance();
byte[] b = input.getBytes(StandardCharsets.UTF_8);
mb.setBytes(b, 0, b.length);
boolean result = CoyoteAdapter.normalize(mb);
mb.toString();
if (expected == null) {
Assert.assertFalse(result);
} else {
Assert.assertTrue(result);
Assert.assertEquals(expected, mb.toString());
}
}
use of org.apache.tomcat.util.buf.MessageBytes in project tomcat by apache.
the class TestCookies method test.
private void test(boolean useRfc6265, String header, Cookie... expected) {
MimeHeaders mimeHeaders = new MimeHeaders();
ServerCookies serverCookies = new ServerCookies(4);
CookieProcessor cookieProcessor;
if (useRfc6265) {
cookieProcessor = new Rfc6265CookieProcessor();
} else {
cookieProcessor = new LegacyCookieProcessor();
}
MessageBytes cookieHeaderValue = mimeHeaders.addValue("Cookie");
byte[] bytes = header.getBytes(StandardCharsets.UTF_8);
cookieHeaderValue.setBytes(bytes, 0, bytes.length);
cookieProcessor.parseCookieHeader(mimeHeaders, serverCookies);
Assert.assertEquals(expected.length, serverCookies.getCookieCount());
for (int i = 0; i < expected.length; i++) {
Cookie cookie = expected[i];
ServerCookie actual = serverCookies.getCookie(i);
Assert.assertEquals(cookie.getVersion(), actual.getVersion());
Assert.assertEquals(cookie.getName(), actual.getName().toString());
actual.getValue().getByteChunk().setCharset(StandardCharsets.UTF_8);
Assert.assertEquals(cookie.getValue(), org.apache.tomcat.util.http.parser.Cookie.unescapeCookieValueRfc2109(actual.getValue().toString()));
if (cookie.getVersion() == 1) {
Assert.assertEquals(cookie.getDomain(), actual.getDomain().toString());
Assert.assertEquals(cookie.getPath(), actual.getPath().toString());
}
}
}
use of org.apache.tomcat.util.buf.MessageBytes in project tomcat by apache.
the class CoyoteAdapter method postParseRequest.
// ------------------------------------------------------ Protected Methods
/**
* Perform the necessary processing after the HTTP headers have been parsed
* to enable the request/response pair to be passed to the start of the
* container pipeline for processing.
*
* @param req The coyote request object
* @param request The catalina request object
* @param res The coyote response object
* @param response The catalina response object
*
* @return <code>true</code> if the request should be passed on to the start
* of the container pipeline, otherwise <code>false</code>
*
* @throws IOException If there is insufficient space in a buffer while
* processing headers
* @throws ServletException If the supported methods of the target servlet
* cannot be determined
*/
protected boolean postParseRequest(org.apache.coyote.Request req, Request request, org.apache.coyote.Response res, Response response) throws IOException, ServletException {
// processor hasn't set it, use the settings from the connector
if (req.scheme().isNull()) {
// Use connector scheme and secure configuration, (defaults to
// "http" and false respectively)
req.scheme().setString(connector.getScheme());
request.setSecure(connector.getSecure());
} else {
// Use processor specified scheme to determine secure state
request.setSecure(req.scheme().equals("https"));
}
// At this point the Host header has been processed.
// Override if the proxyPort/proxyHost are set
String proxyName = connector.getProxyName();
int proxyPort = connector.getProxyPort();
if (proxyPort != 0) {
req.setServerPort(proxyPort);
} else if (req.getServerPort() == -1) {
// Not explicitly set. Use default ports based on the scheme
if (req.scheme().equals("https")) {
req.setServerPort(443);
} else {
req.setServerPort(80);
}
}
if (proxyName != null) {
req.serverName().setString(proxyName);
}
MessageBytes undecodedURI = req.requestURI();
// Check for ping OPTIONS * request
if (undecodedURI.equals("*")) {
if (req.method().equalsIgnoreCase("OPTIONS")) {
StringBuilder allow = new StringBuilder();
allow.append("GET, HEAD, POST, PUT, DELETE");
// Trace if allowed
if (connector.getAllowTrace()) {
allow.append(", TRACE");
}
// Always allow options
allow.append(", OPTIONS");
res.setHeader("Allow", allow.toString());
} else {
res.setStatus(404);
res.setMessage("Not found");
}
connector.getService().getContainer().logAccess(request, response, 0, true);
return false;
}
MessageBytes decodedURI = req.decodedURI();
if (undecodedURI.getType() == MessageBytes.T_BYTES) {
// Copy the raw URI to the decodedURI
decodedURI.duplicate(undecodedURI);
// Parse the path parameters. This will:
// - strip out the path parameters
// - convert the decodedURI to bytes
parsePathParameters(req, request);
// %xx decoding of the URL
try {
req.getURLDecoder().convert(decodedURI, false);
} catch (IOException ioe) {
res.setStatus(400);
res.setMessage("Invalid URI: " + ioe.getMessage());
connector.getService().getContainer().logAccess(request, response, 0, true);
return false;
}
// Normalization
if (!normalize(req.decodedURI())) {
res.setStatus(400);
res.setMessage("Invalid URI");
connector.getService().getContainer().logAccess(request, response, 0, true);
return false;
}
// Character decoding
convertURI(decodedURI, request);
// Check that the URI is still normalized
if (!checkNormalize(req.decodedURI())) {
res.setStatus(400);
res.setMessage("Invalid URI character encoding");
connector.getService().getContainer().logAccess(request, response, 0, true);
return false;
}
} else {
/* The URI is chars or String, and has been sent using an in-memory
* protocol handler. The following assumptions are made:
* - req.requestURI() has been set to the 'original' non-decoded,
* non-normalized URI
* - req.decodedURI() has been set to the decoded, normalized form
* of req.requestURI()
*/
decodedURI.toChars();
// Remove all path parameters; any needed path parameter should be set
// using the request object rather than passing it in the URL
CharChunk uriCC = decodedURI.getCharChunk();
int semicolon = uriCC.indexOf(';');
if (semicolon > 0) {
decodedURI.setChars(uriCC.getBuffer(), uriCC.getStart(), semicolon);
}
}
// Request mapping.
MessageBytes serverName;
if (connector.getUseIPVHosts()) {
serverName = req.localName();
if (serverName.isNull()) {
// well, they did ask for it
res.action(ActionCode.REQ_LOCAL_NAME_ATTRIBUTE, null);
}
} else {
serverName = req.serverName();
}
// Version for the second mapping loop and
// Context that we expect to get for that version
String version = null;
Context versionContext = null;
boolean mapRequired = true;
while (mapRequired) {
// This will map the the latest version by default
connector.getService().getMapper().map(serverName, decodedURI, version, request.getMappingData());
// has been deployed
if (request.getContext() == null) {
res.setStatus(404);
res.setMessage("Not found");
// No context, so use host
Host host = request.getHost();
// Make sure there is a host (might not be during shutdown)
if (host != null) {
host.logAccess(request, response, 0, true);
}
return false;
}
// Now we have the context, we can parse the session ID from the URL
// (if any). Need to do this before we redirect in case we need to
// include the session id in the redirect
String sessionID;
if (request.getServletContext().getEffectiveSessionTrackingModes().contains(SessionTrackingMode.URL)) {
// Get the session ID if there was one
sessionID = request.getPathParameter(SessionConfig.getSessionUriParamName(request.getContext()));
if (sessionID != null) {
request.setRequestedSessionId(sessionID);
request.setRequestedSessionURL(true);
}
}
// Look for session ID in cookies and SSL session
parseSessionCookiesId(request);
parseSessionSslId(request);
sessionID = request.getRequestedSessionId();
mapRequired = false;
if (version != null && request.getContext() == versionContext) {
// We got the version that we asked for. That is it.
} else {
version = null;
versionContext = null;
Context[] contexts = request.getMappingData().contexts;
// No session ID means no possibility of remap
if (contexts != null && sessionID != null) {
// Find the context associated with the session
for (int i = (contexts.length); i > 0; i--) {
Context ctxt = contexts[i - 1];
if (ctxt.getManager().findSession(sessionID) != null) {
// already been mapped?
if (!ctxt.equals(request.getMappingData().context)) {
// Set version so second time through mapping
// the correct context is found
version = ctxt.getWebappVersion();
versionContext = ctxt;
// Reset mapping
request.getMappingData().recycle();
mapRequired = true;
// Recycle cookies and session info in case the
// correct context is configured with different
// settings
request.recycleSessionInfo();
request.recycleCookieInfo(true);
}
break;
}
}
}
}
if (!mapRequired && request.getContext().getPaused()) {
// point.
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// Should never happen
}
// Reset mapping
request.getMappingData().recycle();
mapRequired = true;
}
}
// Possible redirect
MessageBytes redirectPathMB = request.getMappingData().redirectPath;
if (!redirectPathMB.isNull()) {
String redirectPath = URLEncoder.DEFAULT.encode(redirectPathMB.toString(), "UTF-8");
String query = request.getQueryString();
if (request.isRequestedSessionIdFromURL()) {
// This is not optimal, but as this is not very common, it
// shouldn't matter
redirectPath = redirectPath + ";" + SessionConfig.getSessionUriParamName(request.getContext()) + "=" + request.getRequestedSessionId();
}
if (query != null) {
// This is not optimal, but as this is not very common, it
// shouldn't matter
redirectPath = redirectPath + "?" + query;
}
response.sendRedirect(redirectPath);
request.getContext().logAccess(request, response, 0, true);
return false;
}
// Filter trace method
if (!connector.getAllowTrace() && req.method().equalsIgnoreCase("TRACE")) {
Wrapper wrapper = request.getWrapper();
String header = null;
if (wrapper != null) {
String[] methods = wrapper.getServletMethods();
if (methods != null) {
for (int i = 0; i < methods.length; i++) {
if ("TRACE".equals(methods[i])) {
continue;
}
if (header == null) {
header = methods[i];
} else {
header += ", " + methods[i];
}
}
}
}
res.setStatus(405);
res.addHeader("Allow", header);
res.setMessage("TRACE method is not allowed");
request.getContext().logAccess(request, response, 0, true);
return false;
}
doConnectorAuthenticationAuthorization(req, request);
return true;
}
use of org.apache.tomcat.util.buf.MessageBytes in project tomcat by apache.
the class BasicAuthenticator method doAuthenticate.
// --------------------------------------------------------- Public Methods
@Override
protected boolean doAuthenticate(Request request, HttpServletResponse response) throws IOException {
if (checkForCachedAuthentication(request, response, true)) {
return true;
}
// Validate any credentials already included with this request
MessageBytes authorization = request.getCoyoteRequest().getMimeHeaders().getValue("authorization");
if (authorization != null) {
authorization.toBytes();
ByteChunk authorizationBC = authorization.getByteChunk();
BasicCredentials credentials = null;
try {
credentials = new BasicCredentials(authorizationBC);
String username = credentials.getUsername();
String password = credentials.getPassword();
Principal principal = context.getRealm().authenticate(username, password);
if (principal != null) {
register(request, response, principal, HttpServletRequest.BASIC_AUTH, username, password);
return true;
}
} catch (IllegalArgumentException iae) {
if (log.isDebugEnabled()) {
log.debug("Invalid Authorization" + iae.getMessage());
}
}
}
// the request could not be authenticated, so reissue the challenge
StringBuilder value = new StringBuilder(16);
value.append("Basic realm=\"");
value.append(getRealmName(context));
value.append('\"');
response.setHeader(AUTH_HEADER_NAME, value.toString());
response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
return false;
}
Aggregations