2073 lines · 71.5 KB · Java
RawDownload
                        if (connectionState == cs_RENEGOTIATE) {                            // don't use SSLv2Hello when renegotiating                            handshaker.activate(protocolVersion);                        } else {                            handshaker.activate(null);                        }                    }                     /*                     * process the handshake record ... may contain just                     * a partial handshake message or multiple messages.                     *                     * The handshaker state machine will ensure that it's                     * a finished message.                     */                    handshaker.process_record(inputRecord, expectingFinished);                    expectingFinished = false;                     if (handshaker.invalidated) {                        handshaker = null;                        // if state is cs_RENEGOTIATE, revert it to cs_DATA                        if (connectionState == cs_RENEGOTIATE) {                            connectionState = cs_DATA;                        }                    } else if (handshaker.isDone()) {                        // reset the parameters for secure renegotiation.                        secureRenegotiation =                                        handshaker.isSecureRenegotiation();                        clientVerifyData = handshaker.getClientVerifyData();                        serverVerifyData = handshaker.getServerVerifyData();                         sess = handshaker.getSession();                        handshakeSession = null;                        if (!writer.hasOutboundData()) {                            hsStatus = HandshakeStatus.FINISHED;                        }                        handshaker = null;                        connectionState = cs_DATA;                         // No handshakeListeners here.  That's a                        // SSLSocket thing.                    } else if (handshaker.taskOutstanding()) {                        hsStatus = HandshakeStatus.NEED_TASK;                    }                    break;                 case Record.ct_application_data:                    // Pass this right back up to the application.                    if ((connectionState != cs_DATA)                            && (connectionState != cs_RENEGOTIATE)                            && (connectionState != cs_CLOSED)) {                        throw new SSLProtocolException(                            "Data received in non-data state: " +                            connectionState);                    }                     if (expectingFinished) {                        throw new SSLProtocolException                                ("Expecting finished message, received data");                    }                     /*                     * Don't return data once the inbound side is                     * closed.                     */                    if (!inboundDone) {                        ea.scatter(decryptedBB.slice());                    }                    break;                 case Record.ct_alert:                    recvAlert();                    break;                 case Record.ct_change_cipher_spec:                    if ((connectionState != cs_HANDSHAKE                                && connectionState != cs_RENEGOTIATE)                            || inputRecord.available() != 1                            || inputRecord.read() != 1) {                        fatal(Alerts.alert_unexpected_message,                            "illegal change cipher spec msg, state = "                            + connectionState);                    }                     //                    // The first message after a change_cipher_spec                    // record MUST be a "Finished" handshake record,                    // else it's a protocol violation.  We force this                    // to be checked by a minor tweak to the state                    // machine.                    //                    changeReadCiphers();                    // next message MUST be a finished message                    expectingFinished = true;                    break;                 default:                    //                    // TLS requires that unrecognized records be ignored.                    //                    if (debug != null && Debug.isOn("ssl")) {                        System.out.println(threadName() +                            ", Received record type: "                            + inputRecord.contentType());                    }                    break;                } // switch                 /*                 * We only need to check the sequence number state for                 * non-handshaking record.                 *                 * Note that in order to maintain the handshake status                 * properly, we check the sequence number after the last                 * record reading process. As we request renegotiation                 * or close the connection for wrapped sequence number                 * when there is enough sequence number space left to                 * handle a few more records, so the sequence number                 * of the last record cannot be wrapped.                 */                if (connectionState < cs_ERROR && !isInboundDone() &&                        (hsStatus == HandshakeStatus.NOT_HANDSHAKING)) {                    if (checkSequenceNumber(readMAC,                            inputRecord.contentType())) {                        hsStatus = getHSStatus(null);                    }                }            } // synchronized (this)        }         return hsStatus;    }      //    // write/wrap side    //      /**     * Wraps a buffer.  Does a variety of checks before grabbing     * the wrapLock, which blocks multiple wraps from occuring.     */    public SSLEngineResult wrap(ByteBuffer [] appData,            int offset, int length, ByteBuffer netData) throws SSLException {         EngineArgs ea = new EngineArgs(appData, offset, length, netData);         /*         * We can be smarter about using smaller buffer sizes later.         * For now, force it to be large enough to handle any         * valid SSL/TLS record.         */        if (netData.remaining() < outputRecord.maxRecordSize) {            return new SSLEngineResult(                Status.BUFFER_OVERFLOW, getHSStatus(null), 0, 0);        }         try {            synchronized (wrapLock) {                return writeAppRecord(ea);            }        } catch (Exception e) {            ea.resetPos();             fatal(Alerts.alert_internal_error,                "problem unwrapping net record", e);            return null;  // make compiler happy        } finally {            /*             * Just in case something didn't reset limits properly.             */            ea.resetLim();        }    }     /*     * Makes additional checks for unwrap, but this time more     * specific to this packet and the current state of the machine.     */    private SSLEngineResult writeAppRecord(EngineArgs ea) throws IOException {         Status status = null;        HandshakeStatus hsStatus = null;         /*         * See if the handshaker needs to report back some SSLException.         */        checkTaskThrown();         /*         * short circuit if we're closed/closing.         */        if (writer.isOutboundDone()) {            return new SSLEngineResult(Status.CLOSED, getHSStatus(null), 0, 0);        }         /*         * If we're still in cs_HANDSHAKE, make sure it's been         * started.         */        synchronized (this) {            if ((connectionState == cs_HANDSHAKE) ||                    (connectionState == cs_START)) {                kickstartHandshake();                 /*                 * If there's no HS data available to write, we can return                 * without trying to wrap anything.                 */                hsStatus = getHSStatus(null);                 if (hsStatus == HandshakeStatus.NEED_UNWRAP) {                    return new SSLEngineResult(Status.OK, hsStatus, 0, 0);                }            }        }         /*         * Grab a copy of this if it doesn't already exist,         * and we can use it several places before anything major         * happens on this side.  Races aren't critical         * here.         */        if (hsStatus == null) {            hsStatus = getHSStatus(null);        }         /*         * If we have a task outstanding, this *MUST* be done before         * doing any more wrapping, because we could be in the middle         * of receiving a handshake message, for example, a finished         * message which would change the ciphers.         */        if (hsStatus == HandshakeStatus.NEED_TASK) {            return new SSLEngineResult(                Status.OK, hsStatus, 0, 0);        }         /*         * This will obtain any waiting outbound data, or will         * process the outbound appData.         */        try {            synchronized (writeLock) {                hsStatus = writeRecord(outputRecord, ea);            }        } catch (SSLException e) {            throw e;        } catch (IOException e) {            SSLException ex = new SSLException("Write problems");            ex.initCause(e);            throw ex;        }         /*         * writeRecord might have reported some status.         * Now check for the remaining cases.         *         * status above should cover:  NEED_WRAP/FINISHED         */        status = (isOutboundDone() ? Status.CLOSED : Status.OK);        hsStatus = getHSStatus(hsStatus);         return new SSLEngineResult(status, hsStatus,            ea.deltaApp(), ea.deltaNet());    }     /*     * Central point to write/get all of the outgoing data.     */    private HandshakeStatus writeRecord(EngineOutputRecord eor,            EngineArgs ea) throws IOException {         // eventually compress as well.        HandshakeStatus hsStatus =                writer.writeRecord(eor, ea, writeMAC, writeCipher);         /*         * We only need to check the sequence number state for         * non-handshaking record.         *         * Note that in order to maintain the handshake status         * properly, we check the sequence number after the last         * record writing process. As we request renegotiation         * or close the connection for wrapped sequence number         * when there is enough sequence number space left to         * handle a few more records, so the sequence number         * of the last record cannot be wrapped.         */        if (connectionState < cs_ERROR && !isOutboundDone() &&                (hsStatus == HandshakeStatus.NOT_HANDSHAKING)) {            if (checkSequenceNumber(writeMAC, eor.contentType())) {                hsStatus = getHSStatus(null);            }        }         return hsStatus;    }     /*     * Non-application OutputRecords go through here.     */    void writeRecord(EngineOutputRecord eor) throws IOException {        // eventually compress as well.        writer.writeRecord(eor, writeMAC, writeCipher);         /*         * Check the sequence number state         *         * Note that in order to maintain the connection I/O         * properly, we check the sequence number after the last         * record writing process. As we request renegotiation         * or close the connection for wrapped sequence number         * when there is enough sequence number space left to         * handle a few more records, so the sequence number         * of the last record cannot be wrapped.         */        if ((connectionState < cs_ERROR) && !isOutboundDone()) {            checkSequenceNumber(writeMAC, eor.contentType());        }    }     //    // Close code    //     /**     * Check the sequence number state     *     * RFC 4346 states that, "Sequence numbers are of type uint64 and     * may not exceed 2^64-1.  Sequence numbers do not wrap. If a TLS     * implementation would need to wrap a sequence number, it must     * renegotiate instead."     *     * Return true if the handshake status may be changed.     */    private boolean checkSequenceNumber(MAC mac, byte type)            throws IOException {         /*         * Don't bother to check the sequence number for error or         * closed connections, or NULL MAC         */        if (connectionState >= cs_ERROR || mac == MAC.NULL) {            return false;        }         /*         * Conservatively, close the connection immediately when the         * sequence number is close to overflow         */        if (mac.seqNumOverflow()) {            /*             * TLS protocols do not define a error alert for sequence             * number overflow. We use handshake_failure error alert             * for handshaking and bad_record_mac for other records.             */            if (debug != null && Debug.isOn("ssl")) {                System.out.println(threadName() +                    ", sequence number extremely close to overflow " +                    "(2^64-1 packets). Closing connection.");            }             fatal(Alerts.alert_handshake_failure, "sequence number overflow");             return true; // make the compiler happy        }         /*         * Ask for renegotiation when need to renew sequence number.         *         * Don't bother to kickstart the renegotiation when the local is         * asking for it.         */        if ((type != Record.ct_handshake) && mac.seqNumIsHuge()) {            if (debug != null && Debug.isOn("ssl")) {                System.out.println(threadName() + ", request renegotiation " +                        "to avoid sequence number overflow");            }             beginHandshake();            return true;        }         return false;    }     /**     * Signals that no more outbound application data will be sent     * on this <code>SSLEngine</code>.     */    private void closeOutboundInternal() {         if ((debug != null) && Debug.isOn("ssl")) {            System.out.println(threadName() + ", closeOutboundInternal()");        }         /*         * Already closed, ignore         */        if (writer.isOutboundDone()) {            return;        }         switch (connectionState) {         /*         * If we haven't even started yet, don't bother reading inbound.         */        case cs_START:            writer.closeOutbound();            inboundDone = true;            break;         case cs_ERROR:        case cs_CLOSED:            break;         /*         * Otherwise we indicate clean termination.         */        // case cs_HANDSHAKE:        // case cs_DATA:        // case cs_RENEGOTIATE:        default:            warning(Alerts.alert_close_notify);            writer.closeOutbound();            break;        }         // See comment in changeReadCiphers()        writeCipher.dispose();         connectionState = cs_CLOSED;    }     synchronized public void closeOutbound() {        /*         * Dump out a close_notify to the remote side         */        if ((debug != null) && Debug.isOn("ssl")) {            System.out.println(threadName() + ", called closeOutbound()");        }         closeOutboundInternal();    }     /**     * Returns the outbound application data closure state     */    public boolean isOutboundDone() {        return writer.isOutboundDone();    }     /**     * Signals that no more inbound network data will be sent     * to this <code>SSLEngine</code>.     */    private void closeInboundInternal() {         if ((debug != null) && Debug.isOn("ssl")) {            System.out.println(threadName() + ", closeInboundInternal()");        }         /*         * Already closed, ignore         */        if (inboundDone) {            return;        }         closeOutboundInternal();        inboundDone = true;         // See comment in changeReadCiphers()        readCipher.dispose();         connectionState = cs_CLOSED;    }     /*     * Close the inbound side of the connection.  We grab the     * lock here, and do the real work in the internal verison.     * We do check for truncation attacks.     */    synchronized public void closeInbound() throws SSLException {        /*         * Currently closes the outbound side as well.  The IETF TLS         * working group has expressed the opinion that 1/2 open         * connections are not allowed by the spec.  May change         * someday in the future.         */        if ((debug != null) && Debug.isOn("ssl")) {            System.out.println(threadName() + ", called closeInbound()");        }         /*         * No need to throw an Exception if we haven't even started yet.         */

Lines 1001–1500 of 2073. Previous lines

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t