use of io.undertow.util.HeaderMap in project undertow by undertow-io.
the class ChunkedStreamSinkConduit method createLastChunk.
private void createLastChunk(final boolean writeFinal) throws UnsupportedEncodingException {
PooledByteBuffer lastChunkBufferPooled = bufferPool.allocate();
ByteBuffer lastChunkBuffer = lastChunkBufferPooled.getBuffer();
if (writeFinal) {
lastChunkBuffer.put(CRLF);
} else if (chunkingSepBuffer.hasRemaining()) {
//the end of chunk /r/n has not been written yet
//just add it to this buffer to make managing state easier
lastChunkBuffer.put(chunkingSepBuffer);
}
lastChunkBuffer.put(LAST_CHUNK);
//we just assume it will fit
HeaderMap trailers = attachable.getAttachment(HttpAttachments.RESPONSE_TRAILERS);
if (trailers != null && trailers.size() != 0) {
for (HeaderValues trailer : trailers) {
for (String val : trailer) {
trailer.getHeaderName().appendTo(lastChunkBuffer);
lastChunkBuffer.put((byte) ':');
lastChunkBuffer.put((byte) ' ');
lastChunkBuffer.put(val.getBytes(StandardCharsets.US_ASCII));
lastChunkBuffer.put(CRLF);
}
}
lastChunkBuffer.put(CRLF);
} else {
lastChunkBuffer.put(CRLF);
}
//horrible hack
//there is a situation where we can get a buffer leak here if the connection is terminated abnormaly
//this should be fixed once this channel has its lifecycle tied to the connection, same as fixed length
lastChunkBuffer.flip();
ByteBuffer data = ByteBuffer.allocate(lastChunkBuffer.remaining());
data.put(lastChunkBuffer);
data.flip();
this.lastChunkBuffer = new ImmediatePooledByteBuffer(data);
lastChunkBufferPooled.close();
}
use of io.undertow.util.HeaderMap in project undertow by undertow-io.
the class AjpClientRequestClientStreamSinkChannel method createFrameHeaderImpl.
private SendFrameHeader createFrameHeaderImpl() {
if (discardMode) {
getBuffer().clear();
getBuffer().flip();
return new SendFrameHeader(new ImmediatePooledByteBuffer(ByteBuffer.wrap(new byte[0])));
}
PooledByteBuffer pooledHeaderBuffer = getChannel().getBufferPool().allocate();
try {
final ByteBuffer buffer = pooledHeaderBuffer.getBuffer();
ByteBuffer dataBuffer = getBuffer();
int dataInBuffer = dataBuffer.remaining();
if (!firstFrameWritten && requestedChunkSize == 0) {
//we are waiting on a read body chunk
return new SendFrameHeader(dataInBuffer, null);
}
int maxData = getChannel().getSettings().get(UndertowOptions.MAX_AJP_PACKET_SIZE, DEFAULT_MAX_DATA_SIZE) - 6;
if (!firstFrameWritten) {
String contentLength = headers.getFirst(Headers.CONTENT_LENGTH);
if (contentLength != null) {
dataSize = Long.parseLong(contentLength);
requestedChunkSize = maxData;
if (dataInBuffer > dataSize) {
throw UndertowMessages.MESSAGES.fixedLengthOverflow();
}
} else if (isWritesShutdown() && !headers.contains(Headers.TRANSFER_ENCODING)) {
//writes are shut down, go to fixed length
headers.put(Headers.CONTENT_LENGTH, dataInBuffer);
dataSize = dataInBuffer;
requestedChunkSize = maxData;
} else {
headers.put(Headers.TRANSFER_ENCODING, Headers.CHUNKED.toString());
dataSize = -1;
requestedChunkSize = 0;
}
firstFrameWritten = true;
final String path;
final String queryString;
int qsIndex = this.path.indexOf('?');
if (qsIndex == -1) {
path = this.path;
queryString = null;
} else {
path = this.path.substring(0, qsIndex);
queryString = this.path.substring(qsIndex + 1);
}
buffer.put((byte) 0x12);
buffer.put((byte) 0x34);
//we fill the size in later
buffer.put((byte) 0);
buffer.put((byte) 0);
buffer.put((byte) 2);
boolean storeMethod = false;
Integer methodNp = AjpConstants.HTTP_METHODS_MAP.get(method);
if (methodNp == null) {
methodNp = 0xFF;
storeMethod = true;
}
buffer.put((byte) (int) methodNp);
AjpUtils.putHttpString(buffer, protocol);
putString(buffer, path);
putString(buffer, notNull(attachable.getAttachment(ProxiedRequestAttachments.REMOTE_ADDRESS)));
putString(buffer, notNull(attachable.getAttachment(ProxiedRequestAttachments.REMOTE_HOST)));
putString(buffer, notNull(attachable.getAttachment(ProxiedRequestAttachments.SERVER_NAME)));
AjpUtils.putInt(buffer, notNull(attachable.getAttachment(ProxiedRequestAttachments.SERVER_PORT)));
buffer.put((byte) (notNull(attachable.getAttachment(ProxiedRequestAttachments.IS_SSL)) ? 1 : 0));
int headers = 0;
//we need to count the headers
final HeaderMap responseHeaders = this.headers;
for (HttpString name : responseHeaders.getHeaderNames()) {
headers += responseHeaders.get(name).size();
}
AjpUtils.putInt(buffer, headers);
for (final HttpString header : responseHeaders.getHeaderNames()) {
for (String headerValue : responseHeaders.get(header)) {
Integer headerCode = AjpConstants.HEADER_MAP.get(header);
if (headerCode != null) {
AjpUtils.putInt(buffer, headerCode);
} else {
AjpUtils.putHttpString(buffer, header);
}
putString(buffer, headerValue);
}
}
if (queryString != null) {
//query_string
buffer.put((byte) ATTR_QUERY_STRING);
putString(buffer, queryString);
}
String remoteUser = attachable.getAttachment(ProxiedRequestAttachments.REMOTE_USER);
if (remoteUser != null) {
buffer.put((byte) ATTR_REMOTE_USER);
putString(buffer, remoteUser);
}
String authType = attachable.getAttachment(ProxiedRequestAttachments.AUTH_TYPE);
if (authType != null) {
buffer.put((byte) ATTR_AUTH_TYPE);
putString(buffer, authType);
}
String route = attachable.getAttachment(ProxiedRequestAttachments.ROUTE);
if (route != null) {
buffer.put((byte) ATTR_ROUTE);
putString(buffer, route);
}
String sslCert = attachable.getAttachment(ProxiedRequestAttachments.SSL_CERT);
if (sslCert != null) {
buffer.put((byte) ATTR_SSL_CERT);
putString(buffer, sslCert);
}
String sslCypher = attachable.getAttachment(ProxiedRequestAttachments.SSL_CYPHER);
if (sslCypher != null) {
buffer.put((byte) ATTR_SSL_CIPHER);
putString(buffer, sslCypher);
}
byte[] sslSession = attachable.getAttachment(ProxiedRequestAttachments.SSL_SESSION_ID);
if (sslSession != null) {
buffer.put((byte) ATTR_SSL_SESSION);
putString(buffer, FlexBase64.encodeString(sslSession, false));
}
Integer sslKeySize = attachable.getAttachment(ProxiedRequestAttachments.SSL_KEY_SIZE);
if (sslKeySize != null) {
buffer.put((byte) ATTR_SSL_KEY_SIZE);
putString(buffer, sslKeySize.toString());
}
String secret = attachable.getAttachment(ProxiedRequestAttachments.SECRET);
if (secret != null) {
buffer.put((byte) ATTR_SECRET);
putString(buffer, secret);
}
if (storeMethod) {
buffer.put((byte) ATTR_STORED_METHOD);
putString(buffer, method.toString());
}
buffer.put((byte) 0xFF);
int dataLength = buffer.position() - 4;
buffer.put(2, (byte) ((dataLength >> 8) & 0xFF));
buffer.put(3, (byte) (dataLength & 0xFF));
}
if (dataSize == 0) {
//no data, just write out this frame and we are done
buffer.flip();
return new SendFrameHeader(pooledHeaderBuffer);
} else if (requestedChunkSize > 0) {
if (isWritesShutdown() && dataInBuffer == 0) {
buffer.put((byte) 0x12);
buffer.put((byte) 0x34);
buffer.put((byte) 0x00);
buffer.put((byte) 0x02);
buffer.put((byte) 0x00);
buffer.put((byte) 0x00);
buffer.flip();
return new SendFrameHeader(pooledHeaderBuffer);
}
int remaining = dataInBuffer;
remaining = Math.min(remaining, maxData);
remaining = Math.min(remaining, requestedChunkSize);
int bodySize = remaining + 2;
buffer.put((byte) 0x12);
buffer.put((byte) 0x34);
buffer.put((byte) ((bodySize >> 8) & 0xFF));
buffer.put((byte) (bodySize & 0xFF));
buffer.put((byte) ((remaining >> 8) & 0xFF));
buffer.put((byte) (remaining & 0xFF));
requestedChunkSize = 0;
if (remaining < dataInBuffer) {
dataBuffer.limit(getBuffer().position() + remaining);
buffer.flip();
return new SendFrameHeader(dataInBuffer - remaining, pooledHeaderBuffer, dataSize < 0);
} else {
buffer.flip();
return new SendFrameHeader(0, pooledHeaderBuffer, dataSize < 0);
}
} else {
//chunked. We just write the headers, and leave all the data in the buffer
//they need to send us a read body chunk in order to get any data
buffer.flip();
if (buffer.remaining() == 0) {
pooledHeaderBuffer.close();
return new SendFrameHeader(dataInBuffer, null, true);
}
dataBuffer.limit(dataBuffer.position());
return new SendFrameHeader(dataInBuffer, pooledHeaderBuffer, true);
}
} catch (BufferOverflowException e) {
//TODO: UNDERTOW-901
pooledHeaderBuffer.close();
markBroken();
throw e;
}
}
use of io.undertow.util.HeaderMap in project undertow by undertow-io.
the class AjpResponseParser method reset.
public void reset() {
state = 0;
prefix = 0;
numHeaders = 0;
currentHeader = null;
statusCode = 0;
reasonPhrase = null;
headers = new HeaderMap();
stringLength = -1;
currentString = null;
currentIntegerPart = -1;
readHeaders = 0;
}
use of io.undertow.util.HeaderMap in project undertow by undertow-io.
the class DigestAuthenticationMechanism method sendChallenge.
@Override
public ChallengeResult sendChallenge(final HttpServerExchange exchange, final SecurityContext securityContext) {
DigestContext context = exchange.getAttachment(DigestContext.ATTACHMENT_KEY);
boolean stale = context == null ? false : context.isStale();
StringBuilder rb = new StringBuilder(DIGEST_PREFIX);
rb.append(Headers.REALM.toString()).append("=\"").append(realmName).append("\",");
rb.append(Headers.DOMAIN.toString()).append("=\"").append(domain).append("\",");
// based on security constraints.
rb.append(Headers.NONCE.toString()).append("=\"").append(nonceManager.nextNonce(null, exchange)).append("\",");
// Not currently using OPAQUE as it offers no integrity, used for session data leaves it vulnerable to
// session fixation type issues as well.
rb.append(Headers.OPAQUE.toString()).append("=\"00000000000000000000000000000000\"");
if (stale) {
rb.append(",stale=true");
}
if (supportedAlgorithms.size() > 0) {
// This header will need to be repeated once for each algorithm.
rb.append(",").append(Headers.ALGORITHM.toString()).append("=%s");
}
if (qopString != null) {
rb.append(",").append(Headers.QOP.toString()).append("=\"").append(qopString).append("\"");
}
String theChallenge = rb.toString();
HeaderMap responseHeader = exchange.getResponseHeaders();
if (supportedAlgorithms.isEmpty()) {
responseHeader.add(WWW_AUTHENTICATE, theChallenge);
} else {
for (DigestAlgorithm current : supportedAlgorithms) {
responseHeader.add(WWW_AUTHENTICATE, String.format(theChallenge, current.getToken()));
}
}
return new ChallengeResult(true, UNAUTHORIZED);
}
use of io.undertow.util.HeaderMap in project undertow by undertow-io.
the class SSLHeaderHandler method handleRequest.
@Override
public void handleRequest(HttpServerExchange exchange) throws Exception {
HeaderMap requestHeaders = exchange.getRequestHeaders();
final String sessionId = requestHeaders.getFirst(SSL_SESSION_ID);
final String cipher = requestHeaders.getFirst(SSL_CIPHER);
String clientCert = requestHeaders.getFirst(SSL_CLIENT_CERT);
//the proxy client replaces \n with ' '
if (clientCert != null && clientCert.length() > 28) {
StringBuilder sb = new StringBuilder(clientCert.length() + 1);
sb.append(Certificates.BEGIN_CERT);
sb.append('\n');
//core certificate data
sb.append(clientCert.replace(' ', '\n').substring(28, clientCert.length() - 26));
sb.append('\n');
sb.append(Certificates.END_CERT);
clientCert = sb.toString();
}
if (clientCert != null || sessionId != null || cipher != null) {
try {
SSLSessionInfo info = new BasicSSLSessionInfo(sessionId, cipher, clientCert);
exchange.setRequestScheme(HTTPS);
exchange.getConnection().setSslSessionInfo(info);
exchange.addExchangeCompleteListener(CLEAR_SSL_LISTENER);
} catch (java.security.cert.CertificateException | CertificateException e) {
UndertowLogger.REQUEST_LOGGER.debugf(e, "Could not create certificate from header %s", clientCert);
}
}
next.handleRequest(exchange);
}
Aggregations