use of javax.net.ssl.SSLEngineResult in project tomcat by apache.
the class SecureNio2Channel method write.
@Override
public <A> void write(final ByteBuffer src, final long timeout, final TimeUnit unit, final A attachment, final CompletionHandler<Integer, ? super A> handler) {
// Check state
if (closing || closed) {
handler.failed(new IOException(sm.getString("channel.nio.ssl.closing")), attachment);
return;
}
try {
// Prepare the output buffer
netOutBuffer.clear();
// Wrap the source data into the internal buffer
SSLEngineResult result = sslEngine.wrap(src, netOutBuffer);
final int written = result.bytesConsumed();
netOutBuffer.flip();
if (result.getStatus() == Status.OK) {
if (result.getHandshakeStatus() == HandshakeStatus.NEED_TASK) {
tasks();
}
// Write data to the channel
sc.write(netOutBuffer, timeout, unit, attachment, new CompletionHandler<Integer, A>() {
@Override
public void completed(Integer nBytes, A attach) {
if (nBytes.intValue() < 0) {
failed(new EOFException(), attach);
} else if (netOutBuffer.hasRemaining()) {
sc.write(netOutBuffer, timeout, unit, attachment, this);
} else if (written == 0) {
// Special case, start over to avoid code duplication
write(src, timeout, unit, attachment, handler);
} else {
// Call the handler completed method with the
// consumed bytes number
handler.completed(Integer.valueOf(written), attach);
}
}
@Override
public void failed(Throwable exc, A attach) {
handler.failed(exc, attach);
}
});
} else {
throw new IOException(sm.getString("channel.nio.ssl.wrapFail", result.getStatus()));
}
} catch (Exception e) {
handler.failed(e, attachment);
}
}
use of javax.net.ssl.SSLEngineResult in project tomcat by apache.
the class SecureNioChannel method write.
/**
* Writes a sequence of bytes to this channel from the given buffer.
*
* @param src The buffer from which bytes are to be retrieved
* @return The number of bytes written, possibly zero
* @throws IOException If some other I/O error occurs
*/
@Override
public int write(ByteBuffer src) throws IOException {
checkInterruptStatus();
if (src == this.netOutBuffer) {
//we can get here through a recursive call
//by using the NioBlockingSelector
int written = sc.write(src);
return written;
} else {
// Are we closing or closed?
if (closing || closed) {
throw new IOException(sm.getString("channel.nio.ssl.closing"));
}
if (!flush(netOutBuffer)) {
// We haven't emptied out the buffer yet
return 0;
}
// The data buffer is empty, we can reuse the entire buffer.
netOutBuffer.clear();
SSLEngineResult result = sslEngine.wrap(src, netOutBuffer);
// The number of bytes written
int written = result.bytesConsumed();
netOutBuffer.flip();
if (result.getStatus() == Status.OK) {
if (result.getHandshakeStatus() == HandshakeStatus.NEED_TASK)
tasks();
} else {
throw new IOException(sm.getString("channel.nio.ssl.wrapFail", result.getStatus()));
}
// Force a flush
flush(netOutBuffer);
return written;
}
}
use of javax.net.ssl.SSLEngineResult in project tomcat by apache.
the class SecureNioChannel method handshakeWrap.
/**
* Performs the WRAP function
* @param doWrite boolean
* @return the result
* @throws IOException An IO error occurred
*/
protected SSLEngineResult handshakeWrap(boolean doWrite) 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().configureWriteBufferForWrite();
SSLEngineResult result = sslEngine.wrap(getBufHandler().getWriteBuffer(), netOutBuffer);
//prepare the results to be written
netOutBuffer.flip();
//set the status
handshakeStatus = result.getHandshakeStatus();
//optimization, if we do have a writable channel, write it now
if (doWrite)
flush(netOutBuffer);
return result;
}
use of javax.net.ssl.SSLEngineResult in project tomcat by apache.
the class SecureNioChannel method handshakeUnwrap.
/**
* Perform handshake unwrap
* @param doread boolean
* @return the result
* @throws IOException An IO error occurred
*/
protected SSLEngineResult handshakeUnwrap(boolean doread) throws IOException {
if (netInBuffer.position() == netInBuffer.limit()) {
//clear the buffer if we have emptied it out on data
netInBuffer.clear();
}
if (doread) {
//if we have data to read, read it
int read = sc.read(netInBuffer);
if (read == -1)
throw new IOException(sm.getString("channel.nio.ssl.eofDuringHandshake"));
}
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 OpenSSLEngine method wrap.
@Override
public synchronized SSLEngineResult wrap(final ByteBuffer[] srcs, final int offset, final int length, final ByteBuffer dst) 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 (srcs == null || dst == null) {
throw new IllegalArgumentException(sm.getString("engine.nullBuffer"));
}
if (offset >= srcs.length || offset + length > srcs.length) {
throw new IndexOutOfBoundsException(sm.getString("engine.invalidBufferArray", Integer.toString(offset), Integer.toString(length), Integer.toString(srcs.length)));
}
if (dst.isReadOnly()) {
throw new ReadOnlyBufferException();
}
// Prepare OpenSSL to work in server mode and receive handshake
if (accepted == 0) {
beginHandshakeImplicitly();
}
// In handshake or close_notify stages, check if call to wrap was made
// without regard to the handshake status.
SSLEngineResult.HandshakeStatus handshakeStatus = getHandshakeStatus();
if ((!handshakeFinished || engineClosed) && handshakeStatus == SSLEngineResult.HandshakeStatus.NEED_UNWRAP) {
return new SSLEngineResult(getEngineStatus(), SSLEngineResult.HandshakeStatus.NEED_UNWRAP, 0, 0);
}
int bytesProduced = 0;
int pendingNet;
// Check for pending data in the network BIO
pendingNet = SSL.pendingWrittenBytesInBIO(networkBIO);
if (pendingNet > 0) {
// Do we have enough room in destination to write encrypted data?
int capacity = dst.remaining();
if (capacity < pendingNet) {
return new SSLEngineResult(SSLEngineResult.Status.BUFFER_OVERFLOW, handshakeStatus, 0, 0);
}
// Write the pending data from the network BIO into the dst buffer
try {
bytesProduced = readEncryptedData(dst, pendingNet);
} catch (Exception e) {
throw new SSLException(e);
}
// for the receipt the peer's close_notify message -- shutdown.
if (isOutboundDone) {
shutdown();
}
return new SSLEngineResult(getEngineStatus(), getHandshakeStatus(), 0, bytesProduced);
}
// There was no pending data in the network BIO -- encrypt any application data
int bytesConsumed = 0;
int endOffset = offset + length;
for (int i = offset; i < endOffset; ++i) {
final ByteBuffer src = srcs[i];
if (src == null) {
throw new IllegalArgumentException(sm.getString("engine.nullBufferInArray"));
}
while (src.hasRemaining()) {
// Write plain text application data to the SSL engine
try {
bytesConsumed += writePlaintextData(src);
} catch (Exception e) {
throw new SSLException(e);
}
// Check to see if the engine wrote data into the network BIO
pendingNet = SSL.pendingWrittenBytesInBIO(networkBIO);
if (pendingNet > 0) {
// Do we have enough room in dst to write encrypted data?
int capacity = dst.remaining();
if (capacity < pendingNet) {
return new SSLEngineResult(SSLEngineResult.Status.BUFFER_OVERFLOW, getHandshakeStatus(), bytesConsumed, bytesProduced);
}
// Write the pending data from the network BIO into the dst buffer
try {
bytesProduced += readEncryptedData(dst, pendingNet);
} catch (Exception e) {
throw new SSLException(e);
}
return new SSLEngineResult(getEngineStatus(), getHandshakeStatus(), bytesConsumed, bytesProduced);
}
}
}
return new SSLEngineResult(getEngineStatus(), getHandshakeStatus(), bytesConsumed, bytesProduced);
}
Aggregations