/*
 * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package sun.security.ssl;

import java.io.EOFException;
import java.io.IOException;
import java.nio.ByteBuffer;
import javax.crypto.BadPaddingException;
import javax.net.ssl.SSLHandshakeException;

Interface for SSL/(D)TLS transportation.
/** * Interface for SSL/(D)TLS transportation. */
interface SSLTransport {
Returns the host name of the peer.
Returns: the host name of the peer, or null if nothing is available.
/** * Returns the host name of the peer. * * @return the host name of the peer, or null if nothing is * available. */
String getPeerHost();
Returns the port number of the peer.
Returns: the port number of the peer, or -1 if nothing is available.
/** * Returns the port number of the peer. * * @return the port number of the peer, or -1 if nothing is * available. */
int getPeerPort();
Shutdown the transport.
/** * Shutdown the transport. */
default void shutdown() throws IOException { // blank }
Return true if delegated tasks used for handshaking operations.
Returns:true if delegated tasks used for handshaking operations.
/** * Return true if delegated tasks used for handshaking operations. * * @return true if delegated tasks used for handshaking operations. */
boolean useDelegatedTask();
Decodes an array of SSL/(D)TLS network source data into the destination application data buffers. For SSL/TLS connections, if no source data, the network data may be received from the underlying underlying SSL/TLS input stream.
Params:
  • context – the transportation context
  • srcs – an array of ByteBuffers containing the inbound network data
  • srcsOffset – The offset within the srcs buffer array of the first buffer from which bytes are to be retrieved; it must be non-negative and no larger than srcs.length.
  • srcsLength – The maximum number of srcs buffers to be accessed; it must be non-negative and no larger than srcs.length - srcsOffset.
  • dsts – an array of ByteBuffers to hold inbound application data
  • dstsOffset – The offset within the dsts buffer array of the first buffer from which bytes are to be placed; it must be non-negative and no larger than dsts.length.
  • dstsLength – The maximum number of dsts buffers to be accessed; it must be non-negative and no larger than dsts.length - dstsOffset.
Throws:
  • IOException – if a problem was encountered while receiving or decoding networking data
Returns: a Plaintext describing the result of the operation
/** * Decodes an array of SSL/(D)TLS network source data into the * destination application data buffers. * * For SSL/TLS connections, if no source data, the network data may be * received from the underlying underlying SSL/TLS input stream. * * @param context the transportation context * @param srcs an array of {@code ByteBuffers} containing the * inbound network data * @param srcsOffset The offset within the {@code srcs} buffer array * of the first buffer from which bytes are to be * retrieved; it must be non-negative and no larger * than {@code srcs.length}. * @param srcsLength The maximum number of {@code srcs} buffers to be * accessed; it must be non-negative and no larger than * {@code srcs.length} - {@code srcsOffset}. * @param dsts an array of {@code ByteBuffers} to hold inbound * application data * @param dstsOffset The offset within the {@code dsts} buffer array * of the first buffer from which bytes are to be * placed; it must be non-negative and no larger * than {@code dsts.length}. * @param dstsLength The maximum number of {@code dsts} buffers to be * accessed; it must be non-negative and no larger than * {@code dsts.length} - {@code dstsOffset}. * * @return a {@code Plaintext} describing the result of * the operation * @throws IOException if a problem was encountered while receiving or * decoding networking data */
static Plaintext decode(TransportContext context, ByteBuffer[] srcs, int srcsOffset, int srcsLength, ByteBuffer[] dsts, int dstsOffset, int dstsLength) throws IOException { Plaintext[] plaintexts = null; try { plaintexts = context.inputRecord.decode(srcs, srcsOffset, srcsLength); } catch (UnsupportedOperationException unsoe) { // SSLv2Hello // Hack code to deliver SSLv2 error message for SSL/TLS connections. if (!context.sslContext.isDTLS()) { context.outputRecord.encodeV2NoCipher(); if (SSLLogger.isOn && SSLLogger.isOn("ssl")) { SSLLogger.finest("may be talking to SSLv2"); } } throw context.fatal(Alert.UNEXPECTED_MESSAGE, unsoe); } catch (BadPaddingException bpe) { /* * The basic SSLv3 record protection involves (optional) * encryption for privacy, and an integrity check ensuring * data origin authentication. We do them both here, and * throw a fatal alert if the integrity check fails. */ Alert alert = (context.handshakeContext != null) ? Alert.HANDSHAKE_FAILURE : Alert.BAD_RECORD_MAC; throw context.fatal(alert, bpe); } catch (SSLHandshakeException she) { // may be record sequence number overflow throw context.fatal(Alert.HANDSHAKE_FAILURE, she); } catch (EOFException eofe) { // rethrow EOFException, the call will handle it if neede. throw eofe; } catch (IOException ioe) { throw context.fatal(Alert.UNEXPECTED_MESSAGE, ioe); } if (plaintexts == null || plaintexts.length == 0) { // Connection closed or record should be discarded. return Plaintext.PLAINTEXT_NULL; } Plaintext finalPlaintext = Plaintext.PLAINTEXT_NULL; for (Plaintext plainText : plaintexts) { // plainText should never be null for TLS protocols if (plainText == Plaintext.PLAINTEXT_NULL) { // Only happens for DTLS protocols. // // Received a retransmitted flight, and need to retransmit the // previous delivered handshake flight messages. if (context.handshakeContext != null && context.handshakeContext.sslConfig.enableRetransmissions && context.sslContext.isDTLS()) { if (SSLLogger.isOn && SSLLogger.isOn("ssl,verbose")) { SSLLogger.finest("retransmited handshake flight"); } context.outputRecord.launchRetransmission(); } // Otherwise, discard the retransmitted flight. } else if (plainText != null && plainText.contentType != ContentType.APPLICATION_DATA.id) { context.dispatch(plainText); } if (plainText == null) { plainText = Plaintext.PLAINTEXT_NULL; } else { // Fill the destination buffers. if ((dsts != null) && (dstsLength > 0) && (plainText.contentType == ContentType.APPLICATION_DATA.id)) { ByteBuffer fragment = plainText.fragment; int remains = fragment.remaining(); // Should have enough room in the destination buffers. int limit = dstsOffset + dstsLength; for (int i = dstsOffset; ((i < limit) && (remains > 0)); i++) { int amount = Math.min(dsts[i].remaining(), remains); fragment.limit(fragment.position() + amount); dsts[i].put(fragment); remains -= amount; if (!dsts[i].hasRemaining()) { dstsOffset++; } } if (remains > 0) { throw context.fatal(Alert.INTERNAL_ERROR, "no sufficient room in the destination buffers"); } } } finalPlaintext = plainText; } return finalPlaintext; } }