use of javax.net.ssl.SSLEngineResult in project tomcat by apache.
the class OpenSSLEngine method unwrap.
@Override
public synchronized SSLEngineResult unwrap(final ByteBuffer src, final ByteBuffer[] dsts, final int offset, final int length) throws SSLException {
// Check to make sure the engine has not been closed
if (destroyed) {
return new SSLEngineResult(SSLEngineResult.Status.CLOSED, SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING, 0, 0);
}
// Throw required runtime exceptions
if (src == null || dsts == null) {
throw new IllegalArgumentException(sm.getString("engine.nullBuffer"));
}
if (offset >= dsts.length || offset + length > dsts.length) {
throw new IndexOutOfBoundsException(sm.getString("engine.invalidBufferArray", Integer.toString(offset), Integer.toString(length), Integer.toString(dsts.length)));
}
int capacity = 0;
final int endOffset = offset + length;
for (int i = offset; i < endOffset; i++) {
ByteBuffer dst = dsts[i];
if (dst == null) {
throw new IllegalArgumentException(sm.getString("engine.nullBufferInArray"));
}
if (dst.isReadOnly()) {
throw new ReadOnlyBufferException();
}
capacity += dst.remaining();
}
// Prepare OpenSSL to work in server mode and receive handshake
if (accepted == 0) {
beginHandshakeImplicitly();
}
// In handshake or close_notify stages, check if call to unwrap was made
// without regard to the handshake status.
SSLEngineResult.HandshakeStatus handshakeStatus = getHandshakeStatus();
if ((!handshakeFinished || engineClosed) && handshakeStatus == SSLEngineResult.HandshakeStatus.NEED_WRAP) {
return new SSLEngineResult(getEngineStatus(), SSLEngineResult.HandshakeStatus.NEED_WRAP, 0, 0);
}
int len = src.remaining();
// protect against protocol overflow attack vector
if (len > MAX_ENCRYPTED_PACKET_LENGTH) {
isInboundDone = true;
isOutboundDone = true;
engineClosed = true;
shutdown();
throw new SSLException(sm.getString("engine.oversizedPacket"));
}
// Write encrypted data to network BIO
int written = -1;
try {
written = writeEncryptedData(src);
} catch (Exception e) {
throw new SSLException(e);
}
// OpenSSL can return 0 or -1 to these calls if nothing was written
if (written < 0) {
written = 0;
}
// There won't be any application data until we're done handshaking
//
// We first check handshakeFinished to eliminate the overhead of extra JNI call if possible.
int pendingApp = pendingReadableBytesInSSL();
if (!handshakeFinished) {
pendingApp = 0;
}
int bytesProduced = 0;
int idx = offset;
// Do we have enough room in dsts to write decrypted data?
if (capacity < pendingApp) {
return new SSLEngineResult(SSLEngineResult.Status.BUFFER_OVERFLOW, getHandshakeStatus(), written, 0);
}
while (pendingApp > 0) {
// Write decrypted data to dsts buffers
while (idx < endOffset) {
ByteBuffer dst = dsts[idx];
if (!dst.hasRemaining()) {
idx++;
continue;
}
if (pendingApp <= 0) {
break;
}
int bytesRead;
try {
bytesRead = readPlaintextData(dst);
} catch (Exception e) {
throw new SSLException(e);
}
if (bytesRead == 0) {
break;
}
bytesProduced += bytesRead;
pendingApp -= bytesRead;
capacity -= bytesRead;
if (!dst.hasRemaining()) {
idx++;
}
}
if (capacity == 0) {
break;
} else if (pendingApp == 0) {
pendingApp = pendingReadableBytesInSSL();
}
}
// Check to see if we received a close_notify message from the peer
if (!receivedShutdown && (SSL.getShutdown(ssl) & SSL.SSL_RECEIVED_SHUTDOWN) == SSL.SSL_RECEIVED_SHUTDOWN) {
receivedShutdown = true;
closeOutbound();
closeInbound();
}
if (bytesProduced == 0 && written == 0) {
return new SSLEngineResult(SSLEngineResult.Status.BUFFER_UNDERFLOW, getHandshakeStatus(), 0, 0);
} else {
return new SSLEngineResult(getEngineStatus(), getHandshakeStatus(), written, bytesProduced);
}
}
use of javax.net.ssl.SSLEngineResult in project tomcat by apache.
the class SecureNio2Channel method handshakeWrap.
/**
* Performs the WRAP function
* @return the result
* @throws IOException An IO error occurred
*/
protected SSLEngineResult handshakeWrap() throws IOException {
//this should never be called with a network buffer that contains data
//so we can clear it here.
netOutBuffer.clear();
//perform the wrap
getBufHandler().configureWriteBufferForRead();
SSLEngineResult result = sslEngine.wrap(getBufHandler().getWriteBuffer(), netOutBuffer);
//prepare the results to be written
netOutBuffer.flip();
//set the status
handshakeStatus = result.getHandshakeStatus();
return result;
}
use of javax.net.ssl.SSLEngineResult in project tomcat by apache.
the class SecureNio2Channel method read.
@Override
public <A> void read(final ByteBuffer dst, final long timeout, final TimeUnit unit, final A attachment, final CompletionHandler<Integer, ? super A> handler) {
// Check state
if (closing || closed) {
handler.completed(Integer.valueOf(-1), attachment);
return;
}
if (!handshakeComplete) {
throw new IllegalStateException(sm.getString("channel.nio.ssl.incompleteHandshake"));
}
CompletionHandler<Integer, A> readCompletionHandler = new CompletionHandler<Integer, A>() {
@Override
public void completed(Integer nBytes, A attach) {
if (nBytes.intValue() < 0) {
failed(new EOFException(), attach);
} else {
try {
ByteBuffer dst2 = dst;
//the data read
int read = 0;
//the SSL engine result
SSLEngineResult unwrap;
do {
//prepare the buffer
netInBuffer.flip();
//unwrap the data
unwrap = sslEngine.unwrap(netInBuffer, dst2);
//compact the buffer
netInBuffer.compact();
if (unwrap.getStatus() == Status.OK || unwrap.getStatus() == Status.BUFFER_UNDERFLOW) {
//we did receive some data, add it to our total
read += unwrap.bytesProduced();
//perform any tasks if needed
if (unwrap.getHandshakeStatus() == HandshakeStatus.NEED_TASK)
tasks();
//if we need more network data, then bail out for now.
if (unwrap.getStatus() == Status.BUFFER_UNDERFLOW) {
if (read == 0) {
sc.read(netInBuffer, timeout, unit, attachment, this);
return;
} else {
break;
}
}
} else if (unwrap.getStatus() == Status.BUFFER_OVERFLOW) {
if (read > 0) {
// read is attempted
break;
} else {
// since the buffer was created.
if (dst2 == getBufHandler().getReadBuffer()) {
// This is the normal case for this code
getBufHandler().expand(sslEngine.getSession().getApplicationBufferSize());
dst2 = getBufHandler().getReadBuffer();
} else {
// to the caller that the buffer has been replaced.
throw new IOException(sm.getString("channel.nio.ssl.unwrapFailResize", unwrap.getStatus()));
}
}
} else {
// Something else went wrong
throw new IOException(sm.getString("channel.nio.ssl.unwrapFail", unwrap.getStatus()));
}
// continue to unwrap as long as the input buffer has stuff
} while (netInBuffer.position() != 0);
if (!dst2.hasRemaining()) {
unwrapBeforeRead = true;
} else {
unwrapBeforeRead = false;
}
// If everything is OK, so complete
handler.completed(Integer.valueOf(read), attach);
} catch (Exception e) {
failed(e, attach);
}
}
}
@Override
public void failed(Throwable exc, A attach) {
handler.failed(exc, attach);
}
};
if (unwrapBeforeRead || netInBuffer.position() > 0) {
readCompletionHandler.completed(Integer.valueOf(netInBuffer.position()), attachment);
} else {
sc.read(netInBuffer, timeout, unit, attachment, readCompletionHandler);
}
}
use of javax.net.ssl.SSLEngineResult in project tomcat by apache.
the class SecureNio2Channel method handshakeUnwrap.
/**
* Perform handshake unwrap
* @return the result
* @throws IOException An IO error occurred
*/
protected SSLEngineResult handshakeUnwrap() throws IOException {
if (netInBuffer.position() == netInBuffer.limit()) {
//clear the buffer if we have emptied it out on data
netInBuffer.clear();
}
SSLEngineResult result;
boolean cont = false;
//loop while we can perform pure SSLEngine data
do {
//prepare the buffer with the incoming data
netInBuffer.flip();
//call unwrap
getBufHandler().configureReadBufferForWrite();
result = sslEngine.unwrap(netInBuffer, getBufHandler().getReadBuffer());
//compact the buffer, this is an optional method, wonder what would happen if we didn't
netInBuffer.compact();
//read in the status
handshakeStatus = result.getHandshakeStatus();
if (result.getStatus() == SSLEngineResult.Status.OK && result.getHandshakeStatus() == HandshakeStatus.NEED_TASK) {
//execute tasks if we need to
handshakeStatus = tasks();
}
//perform another unwrap?
cont = result.getStatus() == SSLEngineResult.Status.OK && handshakeStatus == HandshakeStatus.NEED_UNWRAP;
} while (cont);
return result;
}
use of javax.net.ssl.SSLEngineResult in project tomcat by apache.
the class SecureNioChannel method read.
/**
* Reads a sequence of bytes from this channel into the given buffer.
*
* @param dst The buffer into which bytes are to be transferred
* @return The number of bytes read, possibly zero, or <tt>-1</tt> if the
* channel has reached end-of-stream
* @throws IOException If some other I/O error occurs
* @throws IllegalArgumentException if the destination buffer is different
* than getBufHandler().getReadBuffer()
*/
@Override
public int read(ByteBuffer dst) throws IOException {
// Make sure we only use the ApplicationBufferHandler's buffers
if (dst != getBufHandler().getReadBuffer() && (getAppReadBufHandler() == null || dst != getAppReadBufHandler().getByteBuffer())) {
throw new IllegalArgumentException(sm.getString("channel.nio.ssl.invalidBuffer"));
}
//are we in the middle of closing or closed?
if (closing || closed)
return -1;
//did we finish our handshake?
if (!handshakeComplete)
throw new IllegalStateException(sm.getString("channel.nio.ssl.incompleteHandshake"));
//read from the network
int netread = sc.read(netInBuffer);
//did we reach EOF? if so send EOF up one layer.
if (netread == -1)
return -1;
//the data read
int read = 0;
//the SSL engine result
SSLEngineResult unwrap;
do {
//prepare the buffer
netInBuffer.flip();
//unwrap the data
unwrap = sslEngine.unwrap(netInBuffer, dst);
//compact the buffer
netInBuffer.compact();
if (unwrap.getStatus() == Status.OK || unwrap.getStatus() == Status.BUFFER_UNDERFLOW) {
//we did receive some data, add it to our total
read += unwrap.bytesProduced();
//perform any tasks if needed
if (unwrap.getHandshakeStatus() == HandshakeStatus.NEED_TASK) {
tasks();
}
//if we need more network data, then bail out for now.
if (unwrap.getStatus() == Status.BUFFER_UNDERFLOW) {
break;
}
} else if (unwrap.getStatus() == Status.BUFFER_OVERFLOW) {
if (read > 0) {
// read is attempted
break;
} else {
// since the buffer was created.
if (dst == getBufHandler().getReadBuffer()) {
// This is the normal case for this code
getBufHandler().expand(sslEngine.getSession().getApplicationBufferSize());
dst = getBufHandler().getReadBuffer();
} else if (dst == getAppReadBufHandler().getByteBuffer()) {
getAppReadBufHandler().expand(sslEngine.getSession().getApplicationBufferSize());
dst = getAppReadBufHandler().getByteBuffer();
} else {
// to the caller that the buffer has been replaced.
throw new IOException(sm.getString("channel.nio.ssl.unwrapFailResize", unwrap.getStatus()));
}
}
} else {
// Something else went wrong
throw new IOException(sm.getString("channel.nio.ssl.unwrapFail", unwrap.getStatus()));
}
} while (//continue to unwrapping as long as the input buffer has stuff
netInBuffer.position() != 0);
return read;
}
Aggregations