2073 lines · 71.5 KB · Java
RawDownload
        if ((connectionState != cs_START) && !recvCN) {            recvCN = true;  // Only receive the Exception once            fatal(Alerts.alert_internal_error,                "Inbound closed before receiving peer's close_notify: " +                "possible truncation attack?");        } else {            /*             * Currently, this is a no-op, but in case we change             * the close inbound code later.             */            closeInboundInternal();        }    }     /**     * Returns the network inbound data closure state     */    synchronized public boolean isInboundDone() {        return inboundDone;    }      //    // Misc stuff    //      /**     * Returns the current <code>SSLSession</code> for this     * <code>SSLEngine</code>     * <P>     * These can be long lived, and frequently correspond to an     * entire login session for some user.     */    synchronized public SSLSession getSession() {        return sess;    }     @Override    synchronized public SSLSession getHandshakeSession() {        return handshakeSession;    }     synchronized void setHandshakeSession(SSLSessionImpl session) {        handshakeSession = session;    }     /**     * Returns a delegated <code>Runnable</code> task for     * this <code>SSLEngine</code>.     */    synchronized public Runnable getDelegatedTask() {        if (handshaker != null) {            return handshaker.getTask();        }        return null;    }      //    // EXCEPTION AND ALERT HANDLING    //     /*     * Send a warning alert.     */    void warning(byte description) {        sendAlert(Alerts.alert_warning, description);    }     synchronized void fatal(byte description, String diagnostic)            throws SSLException {        fatal(description, diagnostic, null);    }     synchronized void fatal(byte description, Throwable cause)            throws SSLException {        fatal(description, null, cause);    }     /*     * We've got a fatal error here, so start the shutdown process.     *     * Because of the way the code was written, we have some code     * calling fatal directly when the "description" is known     * and some throwing Exceptions which are then caught by higher     * levels which then call here.  This code needs to determine     * if one of the lower levels has already started the process.     *     * We won't worry about Error's, if we have one of those,     * we're in worse trouble.  Note:  the networking code doesn't     * deal with Errors either.     */    synchronized void fatal(byte description, String diagnostic,            Throwable cause) throws SSLException {         /*         * If we have no further information, make a general-purpose         * message for folks to see.  We generally have one or the other.         */        if (diagnostic == null) {            diagnostic = "General SSLEngine problem";        }        if (cause == null) {            cause = Alerts.getSSLException(description, cause, diagnostic);        }         /*         * If we've already shutdown because of an error,         * there is nothing we can do except rethrow the exception.         *         * Most exceptions seen here will be SSLExceptions.         * We may find the occasional Exception which hasn't been         * converted to a SSLException, so we'll do it here.         */        if (closeReason != null) {            if ((debug != null) && Debug.isOn("ssl")) {                System.out.println(threadName() +                    ", fatal: engine already closed.  Rethrowing " +                    cause.toString());            }            if (cause instanceof RuntimeException) {                throw (RuntimeException)cause;            } else if (cause instanceof SSLException) {                throw (SSLException)cause;            } else if (cause instanceof Exception) {                SSLException ssle = new SSLException(                    "fatal SSLEngine condition");                ssle.initCause(cause);                throw ssle;            }        }         if ((debug != null) && Debug.isOn("ssl")) {            System.out.println(threadName()                        + ", fatal error: " + description +                        ": " + diagnostic + "\n" + cause.toString());        }         /*         * Ok, this engine's going down.         */        int oldState = connectionState;        connectionState = cs_ERROR;         inboundDone = true;         sess.invalidate();        if (handshakeSession != null) {            handshakeSession.invalidate();        }         /*         * If we haven't even started handshaking yet, no need         * to generate the fatal close alert.         */        if (oldState != cs_START) {            sendAlert(Alerts.alert_fatal, description);        }         if (cause instanceof SSLException) { // only true if != null            closeReason = (SSLException)cause;        } else {            /*             * Including RuntimeExceptions, but we'll throw those             * down below.  The closeReason isn't used again,             * except for null checks.             */            closeReason =                Alerts.getSSLException(description, cause, diagnostic);        }         writer.closeOutbound();         connectionState = cs_CLOSED;         // See comment in changeReadCiphers()        readCipher.dispose();        writeCipher.dispose();         if (cause instanceof RuntimeException) {            throw (RuntimeException)cause;        } else {            throw closeReason;        }    }     /*     * Process an incoming alert ... caller must already have synchronized     * access to "this".     */    private void recvAlert() throws IOException {        byte level = (byte)inputRecord.read();        byte description = (byte)inputRecord.read();        if (description == -1) { // check for short message            fatal(Alerts.alert_illegal_parameter, "Short alert message");        }         if (debug != null && (Debug.isOn("record") ||                Debug.isOn("handshake"))) {            synchronized (System.out) {                System.out.print(threadName());                System.out.print(", RECV " + protocolVersion + " ALERT:  ");                if (level == Alerts.alert_fatal) {                    System.out.print("fatal, ");                } else if (level == Alerts.alert_warning) {                    System.out.print("warning, ");                } else {                    System.out.print("<level " + (0x0ff & level) + ">, ");                }                System.out.println(Alerts.alertDescription(description));            }        }         if (level == Alerts.alert_warning) {            if (description == Alerts.alert_close_notify) {                if (connectionState == cs_HANDSHAKE) {                    fatal(Alerts.alert_unexpected_message,                                "Received close_notify during handshake");                } else {                    recvCN = true;                    closeInboundInternal();  // reply to close                }            } else {                 //                // The other legal warnings relate to certificates,                // e.g. no_certificate, bad_certificate, etc; these                // are important to the handshaking code, which can                // also handle illegal protocol alerts if needed.                //                if (handshaker != null) {                    handshaker.handshakeAlert(description);                }            }        } else { // fatal or unknown level            String reason = "Received fatal alert: "                + Alerts.alertDescription(description);            if (closeReason == null) {                closeReason = Alerts.getSSLException(description, reason);            }            fatal(Alerts.alert_unexpected_message, reason);        }    }      /*     * Emit alerts.  Caller must have synchronized with "this".     */    private void sendAlert(byte level, byte description) {        // the connectionState cannot be cs_START        if (connectionState >= cs_CLOSED) {            return;        }         // For initial handshaking, don't send alert message to peer if        // handshaker has not started.        if (connectionState == cs_HANDSHAKE &&            (handshaker == null || !handshaker.started())) {            return;        }         EngineOutputRecord r = new EngineOutputRecord(Record.ct_alert, this);        r.setVersion(protocolVersion);         boolean useDebug = debug != null && Debug.isOn("ssl");        if (useDebug) {            synchronized (System.out) {                System.out.print(threadName());                System.out.print(", SEND " + protocolVersion + " ALERT:  ");                if (level == Alerts.alert_fatal) {                    System.out.print("fatal, ");                } else if (level == Alerts.alert_warning) {                    System.out.print("warning, ");                } else {                    System.out.print("<level = " + (0x0ff & level) + ">, ");                }                System.out.println("description = "                        + Alerts.alertDescription(description));            }        }         r.write(level);        r.write(description);        try {            writeRecord(r);        } catch (IOException e) {            if (useDebug) {                System.out.println(threadName() +                    ", Exception sending alert: " + e);            }        }    }      //    // VARIOUS OTHER METHODS (COMMON TO SSLSocket)    //      /**     * Controls whether new connections may cause creation of new SSL     * sessions.     *     * As long as handshaking has not started, we can change     * whether we enable session creations.  Otherwise,     * we will need to wait for the next handshake.     */    synchronized public void setEnableSessionCreation(boolean flag) {        enableSessionCreation = flag;         if ((handshaker != null) && !handshaker.activated()) {            handshaker.setEnableSessionCreation(enableSessionCreation);        }    }     /**     * Returns true if new connections may cause creation of new SSL     * sessions.     */    synchronized public boolean getEnableSessionCreation() {        return enableSessionCreation;    }      /**     * Sets the flag controlling whether a server mode engine     * *REQUIRES* SSL client authentication.     *     * As long as handshaking has not started, we can change     * whether client authentication is needed.  Otherwise,     * we will need to wait for the next handshake.     */    synchronized public void setNeedClientAuth(boolean flag) {        doClientAuth = (flag ?            SSLEngineImpl.clauth_required : SSLEngineImpl.clauth_none);         if ((handshaker != null) &&                (handshaker instanceof ServerHandshaker) &&                !handshaker.activated()) {            ((ServerHandshaker) handshaker).setClientAuth(doClientAuth);        }    }     synchronized public boolean getNeedClientAuth() {        return (doClientAuth == SSLEngineImpl.clauth_required);    }     /**     * Sets the flag controlling whether a server mode engine     * *REQUESTS* SSL client authentication.     *     * As long as handshaking has not started, we can change     * whether client authentication is requested.  Otherwise,     * we will need to wait for the next handshake.     */    synchronized public void setWantClientAuth(boolean flag) {        doClientAuth = (flag ?            SSLEngineImpl.clauth_requested : SSLEngineImpl.clauth_none);         if ((handshaker != null) &&                (handshaker instanceof ServerHandshaker) &&                !handshaker.activated()) {            ((ServerHandshaker) handshaker).setClientAuth(doClientAuth);        }    }     synchronized public boolean getWantClientAuth() {        return (doClientAuth == SSLEngineImpl.clauth_requested);    }      /**     * Sets the flag controlling whether the engine is in SSL     * client or server mode.  Must be called before any SSL     * traffic has started.     */    synchronized public void setUseClientMode(boolean flag) {        switch (connectionState) {         case cs_START:            /*             * If we need to change the engine mode and the enabled             * protocols haven't specifically been set by the user,             * change them to the corresponding default ones.             */            if (roleIsServer != (!flag) &&                    sslContext.isDefaultProtocolList(enabledProtocols)) {                enabledProtocols = sslContext.getDefaultProtocolList(!flag);            }             roleIsServer = !flag;            serverModeSet = true;            break;         case cs_HANDSHAKE:            /*             * If we have a handshaker, but haven't started             * SSL traffic, we can throw away our current             * handshaker, and start from scratch.  Don't             * need to call doneConnect() again, we already             * have the streams.             */            assert(handshaker != null);            if (!handshaker.activated()) {                /*                 * If we need to change the engine mode and the enabled                 * protocols haven't specifically been set by the user,                 * change them to the corresponding default ones.                 */                if (roleIsServer != (!flag) &&                        sslContext.isDefaultProtocolList(enabledProtocols)) {                    enabledProtocols = sslContext.getDefaultProtocolList(!flag);                }                 roleIsServer = !flag;                connectionState = cs_START;                initHandshaker();                break;            }             // If handshake has started, that's an error.  Fall through...         default:            if (debug != null && Debug.isOn("ssl")) {                System.out.println(threadName() +                    ", setUseClientMode() invoked in state = " +                    connectionState);            }             /*             * We can let them continue if they catch this correctly,             * we don't need to shut this down.             */            throw new IllegalArgumentException(                "Cannot change mode after SSL traffic has started");        }    }     synchronized public boolean getUseClientMode() {        return !roleIsServer;    }      /**     * Returns the names of the cipher suites which could be enabled for use     * on an SSL connection.  Normally, only a subset of these will actually     * be enabled by default, since this list may include cipher suites which     * do not support the mutual authentication of servers and clients, or     * which do not protect data confidentiality.  Servers may also need     * certain kinds of certificates to use certain cipher suites.     *     * @return an array of cipher suite names     */    public String[] getSupportedCipherSuites() {        return sslContext.getSuportedCipherSuiteList().toStringArray();    }     /**     * Controls which particular cipher suites are enabled for use on     * this connection.  The cipher suites must have been listed by     * getCipherSuites() as being supported.  Even if a suite has been     * enabled, it might never be used if no peer supports it or the     * requisite certificates (and private keys) are not available.     *     * @param suites Names of all the cipher suites to enable.     */    synchronized public void setEnabledCipherSuites(String[] suites) {        enabledCipherSuites = new CipherSuiteList(suites);        if ((handshaker != null) && !handshaker.activated()) {            handshaker.setEnabledCipherSuites(enabledCipherSuites);        }    }     /**     * Returns the names of the SSL cipher suites which are currently enabled     * for use on this connection.  When an SSL engine is first created,     * all enabled cipher suites <em>(a)</em> protect data confidentiality,     * by traffic encryption, and <em>(b)</em> can mutually authenticate     * both clients and servers.  Thus, in some environments, this value     * might be empty.     *     * @return an array of cipher suite names     */    synchronized public String[] getEnabledCipherSuites() {        return enabledCipherSuites.toStringArray();    }      /**     * Returns the protocols that are supported by this implementation.     * A subset of the supported protocols may be enabled for this connection     * @return an array of protocol names.     */    public String[] getSupportedProtocols() {        return sslContext.getSuportedProtocolList().toStringArray();    }     /**     * Controls which protocols are enabled for use on

Lines 1501–2000 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