| 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 */  | 
 | 
 | 
 | 
package sun.security.ssl;  | 
 | 
 | 
 | 
import java.io.IOException;  | 
 | 
import java.nio.ByteBuffer;  | 
 | 
import java.text.MessageFormat;  | 
 | 
import java.util.Arrays;  | 
 | 
import java.util.Locale;  | 
 | 
import javax.net.ssl.SSLProtocolException;  | 
 | 
import sun.security.ssl.ClientHello.ClientHelloMessage;  | 
 | 
import static sun.security.ssl.SSLExtension.CH_RENEGOTIATION_INFO;  | 
 | 
import sun.security.ssl.SSLExtension.ExtensionConsumer;  | 
 | 
import static sun.security.ssl.SSLExtension.SH_RENEGOTIATION_INFO;  | 
 | 
import sun.security.ssl.SSLExtension.SSLExtensionSpec;  | 
 | 
import sun.security.ssl.SSLHandshake.HandshakeMessage;  | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 */  | 
 | 
final class RenegoInfoExtension { | 
 | 
    static final HandshakeProducer chNetworkProducer =  | 
 | 
            new CHRenegotiationInfoProducer();  | 
 | 
    static final ExtensionConsumer chOnLoadConsumer =  | 
 | 
            new CHRenegotiationInfoConsumer();  | 
 | 
    static final HandshakeAbsence chOnLoadAbsence =  | 
 | 
            new CHRenegotiationInfoAbsence();  | 
 | 
 | 
 | 
    static final HandshakeProducer shNetworkProducer =  | 
 | 
            new SHRenegotiationInfoProducer();  | 
 | 
    static final ExtensionConsumer shOnLoadConsumer =  | 
 | 
            new SHRenegotiationInfoConsumer();  | 
 | 
    static final HandshakeAbsence shOnLoadAbsence =  | 
 | 
            new SHRenegotiationInfoAbsence();  | 
 | 
 | 
 | 
    static final SSLStringizer rniStringizer =  | 
 | 
            new RenegotiationInfoStringizer();  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    static final class RenegotiationInfoSpec implements SSLExtensionSpec { | 
 | 
          | 
 | 
        static final RenegotiationInfoSpec NOMINAL =  | 
 | 
                new RenegotiationInfoSpec(new byte[0]);  | 
 | 
 | 
 | 
        private final byte[] renegotiatedConnection;  | 
 | 
 | 
 | 
        private RenegotiationInfoSpec(byte[] renegotiatedConnection) { | 
 | 
            this.renegotiatedConnection = Arrays.copyOf(  | 
 | 
                    renegotiatedConnection, renegotiatedConnection.length);  | 
 | 
        }  | 
 | 
 | 
 | 
        private RenegotiationInfoSpec(ByteBuffer m) throws IOException { | 
 | 
              | 
 | 
            if (!m.hasRemaining() || m.remaining() < 1) { | 
 | 
                throw new SSLProtocolException(  | 
 | 
                    "Invalid renegotiation_info extension data: " +  | 
 | 
                    "insufficient data");  | 
 | 
            }  | 
 | 
            this.renegotiatedConnection = Record.getBytes8(m);  | 
 | 
        }  | 
 | 
 | 
 | 
        @Override  | 
 | 
        public String toString() { | 
 | 
            MessageFormat messageFormat = new MessageFormat(  | 
 | 
                "\"renegotiated connection\": '['{0}']'", Locale.ENGLISH); | 
 | 
            if (renegotiatedConnection.length == 0) { | 
 | 
                Object[] messageFields = { | 
 | 
                        "<no renegotiated connection>"  | 
 | 
                    };  | 
 | 
                return messageFormat.format(messageFields);  | 
 | 
            } else { | 
 | 
                Object[] messageFields = { | 
 | 
                        Utilities.toHexString(renegotiatedConnection)  | 
 | 
                    };  | 
 | 
                return messageFormat.format(messageFields);  | 
 | 
            }  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    private static final  | 
 | 
            class RenegotiationInfoStringizer implements SSLStringizer { | 
 | 
        @Override  | 
 | 
        public String toString(ByteBuffer buffer) { | 
 | 
            try { | 
 | 
                return (new RenegotiationInfoSpec(buffer)).toString();  | 
 | 
            } catch (IOException ioe) { | 
 | 
                  | 
 | 
                return ioe.getMessage();  | 
 | 
            }  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    private static final  | 
 | 
            class CHRenegotiationInfoProducer implements HandshakeProducer { | 
 | 
          | 
 | 
        private CHRenegotiationInfoProducer() { | 
 | 
            // blank  | 
 | 
        }  | 
 | 
 | 
 | 
        @Override  | 
 | 
        public byte[] produce(ConnectionContext context,  | 
 | 
                HandshakeMessage message) throws IOException { | 
 | 
              | 
 | 
            ClientHandshakeContext chc = (ClientHandshakeContext)context;  | 
 | 
 | 
 | 
              | 
 | 
            if (!chc.sslConfig.isAvailable(CH_RENEGOTIATION_INFO)) { | 
 | 
                if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { | 
 | 
                    SSLLogger.fine(  | 
 | 
                            "Ignore unavailable renegotiation_info extension");  | 
 | 
                }  | 
 | 
 | 
 | 
                return null;  | 
 | 
            }  | 
 | 
 | 
 | 
            if (!chc.conContext.isNegotiated) { | 
 | 
                if (chc.activeCipherSuites.contains(  | 
 | 
                        CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV)) { | 
 | 
                      | 
 | 
                    return null;  | 
 | 
                }  | 
 | 
 | 
 | 
                // initial handshaking.  | 
 | 
                //  | 
 | 
                // If this is the initial handshake for a connection, then the  | 
 | 
                // "renegotiated_connection" field is of zero length in both  | 
 | 
                  | 
 | 
                byte[] extData = new byte[] { 0x00 }; | 
 | 
                chc.handshakeExtensions.put(  | 
 | 
                        CH_RENEGOTIATION_INFO, RenegotiationInfoSpec.NOMINAL);  | 
 | 
 | 
 | 
                return extData;  | 
 | 
            } else if (chc.conContext.secureRenegotiation) { | 
 | 
                // secure renegotiation  | 
 | 
                //  | 
 | 
                // For ClientHello handshake message in renegotiation, this  | 
 | 
                  | 
 | 
                byte[] extData =  | 
 | 
                        new byte[chc.conContext.clientVerifyData.length + 1];  | 
 | 
                ByteBuffer m = ByteBuffer.wrap(extData);  | 
 | 
                Record.putBytes8(m, chc.conContext.clientVerifyData);  | 
 | 
 | 
 | 
                // The conContext.clientVerifyData will be used for further  | 
 | 
                // processing, so it does not matter to save whatever in the  | 
 | 
                  | 
 | 
                chc.handshakeExtensions.put(  | 
 | 
                        CH_RENEGOTIATION_INFO, RenegotiationInfoSpec.NOMINAL);  | 
 | 
 | 
 | 
                return extData;  | 
 | 
            } else {     | 
 | 
                if (HandshakeContext.allowUnsafeRenegotiation) { | 
 | 
                    if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { | 
 | 
                        SSLLogger.warning("Using insecure renegotiation"); | 
 | 
                    }  | 
 | 
 | 
 | 
                    return null;  | 
 | 
                } else { | 
 | 
                      | 
 | 
                    throw chc.conContext.fatal(Alert.HANDSHAKE_FAILURE,  | 
 | 
                            "insecure renegotiation is not allowed");  | 
 | 
                }  | 
 | 
            }  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    private static final  | 
 | 
            class CHRenegotiationInfoConsumer implements ExtensionConsumer { | 
 | 
          | 
 | 
        private CHRenegotiationInfoConsumer() { | 
 | 
            // blank  | 
 | 
        }  | 
 | 
 | 
 | 
        @Override  | 
 | 
        public void consume(ConnectionContext context,  | 
 | 
            HandshakeMessage message, ByteBuffer buffer) throws IOException { | 
 | 
 | 
 | 
              | 
 | 
            ServerHandshakeContext shc = (ServerHandshakeContext)context;  | 
 | 
 | 
 | 
              | 
 | 
            if (!shc.sslConfig.isAvailable(CH_RENEGOTIATION_INFO)) { | 
 | 
                if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { | 
 | 
                    SSLLogger.fine("Ignore unavailable extension: " + | 
 | 
                            CH_RENEGOTIATION_INFO.name);  | 
 | 
                }  | 
 | 
                return;       | 
 | 
            }  | 
 | 
 | 
 | 
              | 
 | 
            RenegotiationInfoSpec spec;  | 
 | 
            try { | 
 | 
                spec = new RenegotiationInfoSpec(buffer);  | 
 | 
            } catch (IOException ioe) { | 
 | 
                throw shc.conContext.fatal(Alert.UNEXPECTED_MESSAGE, ioe);  | 
 | 
            }  | 
 | 
 | 
 | 
            if (!shc.conContext.isNegotiated) { | 
 | 
                  | 
 | 
                if (spec.renegotiatedConnection.length != 0) { | 
 | 
                    throw shc.conContext.fatal(Alert.UNEXPECTED_MESSAGE,  | 
 | 
                        "Invalid renegotiation_info extension data: not empty");  | 
 | 
                }  | 
 | 
                shc.conContext.secureRenegotiation = true;  | 
 | 
            } else { | 
 | 
                if (!shc.conContext.secureRenegotiation) { | 
 | 
                    // Unexpected RI extension for insecure renegotiation,  | 
 | 
                      | 
 | 
                    throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,  | 
 | 
                            "The renegotiation_info is present in a insecure " +  | 
 | 
                            "renegotiation");  | 
 | 
                } else { | 
 | 
                      | 
 | 
                    if (!Arrays.equals(shc.conContext.clientVerifyData,  | 
 | 
                            spec.renegotiatedConnection)) { | 
 | 
                        throw shc.conContext.fatal(Alert.UNEXPECTED_MESSAGE,  | 
 | 
                            "Invalid renegotiation_info extension data: " +  | 
 | 
                            "incorrect verify data in ClientHello");  | 
 | 
                    }  | 
 | 
                }  | 
 | 
            }  | 
 | 
 | 
 | 
            // Update the context.  | 
 | 
            //  | 
 | 
            // The conContext.clientVerifyData will be used for further  | 
 | 
            // processing, so it does not matter to save whatever in the  | 
 | 
              | 
 | 
            shc.handshakeExtensions.put(  | 
 | 
                    CH_RENEGOTIATION_INFO, RenegotiationInfoSpec.NOMINAL);  | 
 | 
 | 
 | 
            // No impact on session resumption.  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    private static final  | 
 | 
            class CHRenegotiationInfoAbsence implements HandshakeAbsence { | 
 | 
        @Override  | 
 | 
        public void absent(ConnectionContext context,  | 
 | 
                HandshakeMessage message) throws IOException { | 
 | 
              | 
 | 
            ServerHandshakeContext shc = (ServerHandshakeContext)context;  | 
 | 
            ClientHelloMessage clientHello = (ClientHelloMessage)message;  | 
 | 
 | 
 | 
            if (!shc.conContext.isNegotiated) { | 
 | 
                  | 
 | 
                for (int id : clientHello.cipherSuiteIds) { | 
 | 
                    if (id ==  | 
 | 
                            CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV.id) { | 
 | 
                        if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { | 
 | 
                            SSLLogger.finest(  | 
 | 
                                "Safe renegotiation, using the SCSV signgling");  | 
 | 
                        }  | 
 | 
                        shc.conContext.secureRenegotiation = true;  | 
 | 
                        return;  | 
 | 
                    }  | 
 | 
                }  | 
 | 
 | 
 | 
                if (!HandshakeContext.allowLegacyHelloMessages) { | 
 | 
                    throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,  | 
 | 
                        "Failed to negotiate the use of secure renegotiation");  | 
 | 
                }   // otherwise, allow legacy hello message  | 
 | 
 | 
 | 
                if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { | 
 | 
                    SSLLogger.warning("Warning: No renegotiation " + | 
 | 
                        "indication in ClientHello, allow legacy ClientHello");  | 
 | 
                }  | 
 | 
 | 
 | 
                shc.conContext.secureRenegotiation = false;  | 
 | 
            } else if (shc.conContext.secureRenegotiation) { | 
 | 
                  | 
 | 
                throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,  | 
 | 
                        "Inconsistent secure renegotiation indication");  | 
 | 
            } else {     | 
 | 
                if (HandshakeContext.allowUnsafeRenegotiation) { | 
 | 
                    if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { | 
 | 
                        SSLLogger.warning("Using insecure renegotiation"); | 
 | 
                    }  | 
 | 
                } else { | 
 | 
                    // Unsafe renegotiation should have been aborted in  | 
 | 
                      | 
 | 
                    if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { | 
 | 
                        SSLLogger.fine("Terminate insecure renegotiation"); | 
 | 
                    }  | 
 | 
                    throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,  | 
 | 
                        "Unsafe renegotiation is not allowed");  | 
 | 
                }  | 
 | 
            }  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    private static final  | 
 | 
            class SHRenegotiationInfoProducer implements HandshakeProducer { | 
 | 
          | 
 | 
        private SHRenegotiationInfoProducer() { | 
 | 
            // blank  | 
 | 
        }  | 
 | 
 | 
 | 
        @Override  | 
 | 
        public byte[] produce(ConnectionContext context,  | 
 | 
                HandshakeMessage message) throws IOException { | 
 | 
              | 
 | 
            ServerHandshakeContext shc = (ServerHandshakeContext)context;  | 
 | 
 | 
 | 
              | 
 | 
            RenegotiationInfoSpec requestedSpec = (RenegotiationInfoSpec)  | 
 | 
                    shc.handshakeExtensions.get(CH_RENEGOTIATION_INFO);  | 
 | 
            if (requestedSpec == null && !shc.conContext.secureRenegotiation) { | 
 | 
                // Ignore, no renegotiation_info extension or SCSV signgling  | 
 | 
                  | 
 | 
                if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { | 
 | 
                    SSLLogger.finest(  | 
 | 
                        "Ignore unavailable renegotiation_info extension");  | 
 | 
                }  | 
 | 
                return null;          | 
 | 
            }  | 
 | 
 | 
 | 
            if (!shc.conContext.secureRenegotiation) { | 
 | 
                  | 
 | 
                if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { | 
 | 
                    SSLLogger.finest(  | 
 | 
                        "No secure renegotiation has been negotiated");  | 
 | 
                }  | 
 | 
                return null;          | 
 | 
            }  | 
 | 
 | 
 | 
            if (!shc.conContext.isNegotiated) { | 
 | 
                // initial handshaking.  | 
 | 
                //  | 
 | 
                // If this is the initial handshake for a connection, then the  | 
 | 
                // "renegotiated_connection" field is of zero length in both  | 
 | 
                  | 
 | 
                byte[] extData = new byte[] { 0x00 }; | 
 | 
 | 
 | 
                // The conContext.client/serverVerifyData will be used for  | 
 | 
                // further processing, so it does not matter to save whatever  | 
 | 
                  | 
 | 
                shc.handshakeExtensions.put(  | 
 | 
                        SH_RENEGOTIATION_INFO, RenegotiationInfoSpec.NOMINAL);  | 
 | 
 | 
 | 
                return extData;  | 
 | 
            } else { | 
 | 
                // secure renegotiation  | 
 | 
                //  | 
 | 
                // For secure renegotiation, the server MUST include a  | 
 | 
                // "renegotiation_info" extension containing the saved  | 
 | 
                  | 
 | 
                int infoLen = shc.conContext.clientVerifyData.length +  | 
 | 
                              shc.conContext.serverVerifyData.length;  | 
 | 
                byte[] extData = new byte[infoLen + 1];  | 
 | 
                ByteBuffer m = ByteBuffer.wrap(extData);  | 
 | 
                Record.putInt8(m, infoLen);  | 
 | 
                m.put(shc.conContext.clientVerifyData);  | 
 | 
                m.put(shc.conContext.serverVerifyData);  | 
 | 
 | 
 | 
                // The conContext.client/serverVerifyData will be used for  | 
 | 
                // further processing, so it does not matter to save whatever  | 
 | 
                  | 
 | 
                shc.handshakeExtensions.put(  | 
 | 
                        SH_RENEGOTIATION_INFO, RenegotiationInfoSpec.NOMINAL);  | 
 | 
 | 
 | 
                return extData;  | 
 | 
            }  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    private static final  | 
 | 
            class SHRenegotiationInfoConsumer implements ExtensionConsumer { | 
 | 
          | 
 | 
        private SHRenegotiationInfoConsumer() { | 
 | 
            // blank  | 
 | 
        }  | 
 | 
 | 
 | 
        @Override  | 
 | 
        public void consume(ConnectionContext context,  | 
 | 
            HandshakeMessage message, ByteBuffer buffer) throws IOException { | 
 | 
              | 
 | 
            ClientHandshakeContext chc = (ClientHandshakeContext)context;  | 
 | 
 | 
 | 
            // In response to the client renegotiation_info extension request  | 
 | 
              | 
 | 
            RenegotiationInfoSpec requestedSpec = (RenegotiationInfoSpec)  | 
 | 
                    chc.handshakeExtensions.get(CH_RENEGOTIATION_INFO);  | 
 | 
            if (requestedSpec == null &&  | 
 | 
                    !chc.activeCipherSuites.contains(  | 
 | 
                            CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV)) { | 
 | 
                throw chc.conContext.fatal(Alert.INTERNAL_ERROR,  | 
 | 
                    "Missing renegotiation_info and SCSV detected in " +  | 
 | 
                    "ClientHello");  | 
 | 
            }  | 
 | 
 | 
 | 
              | 
 | 
            RenegotiationInfoSpec spec;  | 
 | 
            try { | 
 | 
                spec = new RenegotiationInfoSpec(buffer);  | 
 | 
            } catch (IOException ioe) { | 
 | 
                throw chc.conContext.fatal(Alert.UNEXPECTED_MESSAGE, ioe);  | 
 | 
            }  | 
 | 
 | 
 | 
 | 
 | 
            if (!chc.conContext.isNegotiated) {     // initial handshake | 
 | 
                // If the extension is present, set the secure_renegotiation  | 
 | 
                // flag to TRUE.  The client MUST then verify that the  | 
 | 
                // length of the "renegotiated_connection" field is zero,  | 
 | 
                // and if it is not, MUST abort the handshake (by sending  | 
 | 
                  | 
 | 
                if (spec.renegotiatedConnection.length != 0) { | 
 | 
                    throw chc.conContext.fatal(Alert.HANDSHAKE_FAILURE,  | 
 | 
                        "Invalid renegotiation_info in ServerHello: " +  | 
 | 
                        "not empty renegotiated_connection");  | 
 | 
                }  | 
 | 
 | 
 | 
                chc.conContext.secureRenegotiation = true;  | 
 | 
            } else {        // renegotiation | 
 | 
                // The client MUST then verify that the first half of the  | 
 | 
                // "renegotiated_connection" field is equal to the saved  | 
 | 
                // client_verify_data value, and the second half is equal to the  | 
 | 
                // saved server_verify_data value.  If they are not, the client  | 
 | 
                  | 
 | 
                int infoLen = chc.conContext.clientVerifyData.length +  | 
 | 
                              chc.conContext.serverVerifyData.length;  | 
 | 
                if (spec.renegotiatedConnection.length != infoLen) { | 
 | 
                    throw chc.conContext.fatal(Alert.HANDSHAKE_FAILURE,  | 
 | 
                        "Invalid renegotiation_info in ServerHello: " +  | 
 | 
                        "invalid renegotiated_connection length (" + | 
 | 
                        spec.renegotiatedConnection.length + ")");  | 
 | 
                }  | 
 | 
 | 
 | 
                byte[] cvd = chc.conContext.clientVerifyData;  | 
 | 
                if (!Utilities.equals(spec.renegotiatedConnection,  | 
 | 
                        0, cvd.length, cvd, 0, cvd.length)) { | 
 | 
                    throw chc.conContext.fatal(Alert.HANDSHAKE_FAILURE,  | 
 | 
                        "Invalid renegotiation_info in ServerHello: " +  | 
 | 
                        "unmatched client_verify_data value");  | 
 | 
                }  | 
 | 
                byte[] svd = chc.conContext.serverVerifyData;  | 
 | 
                if (!Utilities.equals(spec.renegotiatedConnection,  | 
 | 
                        cvd.length, infoLen, svd, 0, svd.length)) { | 
 | 
                    throw chc.conContext.fatal(Alert.HANDSHAKE_FAILURE,  | 
 | 
                        "Invalid renegotiation_info in ServerHello: " +  | 
 | 
                        "unmatched server_verify_data value");  | 
 | 
                }  | 
 | 
            }  | 
 | 
 | 
 | 
              | 
 | 
            chc.handshakeExtensions.put(  | 
 | 
                    SH_RENEGOTIATION_INFO, RenegotiationInfoSpec.NOMINAL);  | 
 | 
 | 
 | 
            // No impact on session resumption.  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    private static final  | 
 | 
            class SHRenegotiationInfoAbsence implements HandshakeAbsence { | 
 | 
        @Override  | 
 | 
        public void absent(ConnectionContext context,  | 
 | 
                HandshakeMessage message) throws IOException { | 
 | 
              | 
 | 
            ClientHandshakeContext chc = (ClientHandshakeContext)context;  | 
 | 
 | 
 | 
            // In response to the client renegotiation_info extension request  | 
 | 
              | 
 | 
            RenegotiationInfoSpec requestedSpec = (RenegotiationInfoSpec)  | 
 | 
                    chc.handshakeExtensions.get(CH_RENEGOTIATION_INFO);  | 
 | 
            if (requestedSpec == null &&  | 
 | 
                    !chc.activeCipherSuites.contains(  | 
 | 
                            CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV)) { | 
 | 
                throw chc.conContext.fatal(Alert.INTERNAL_ERROR,  | 
 | 
                    "Missing renegotiation_info and SCSV detected in " +  | 
 | 
                    "ClientHello");  | 
 | 
            }  | 
 | 
 | 
 | 
            if (!chc.conContext.isNegotiated) { | 
 | 
                  | 
 | 
                if (!HandshakeContext.allowLegacyHelloMessages) { | 
 | 
                    throw chc.conContext.fatal(Alert.HANDSHAKE_FAILURE,  | 
 | 
                        "Failed to negotiate the use of secure renegotiation");  | 
 | 
                }   // otherwise, allow legacy hello message  | 
 | 
 | 
 | 
                if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { | 
 | 
                    SSLLogger.warning("Warning: No renegotiation " + | 
 | 
                        "indication in ServerHello, allow legacy ServerHello");  | 
 | 
                }  | 
 | 
 | 
 | 
                chc.conContext.secureRenegotiation = false;  | 
 | 
            } else if (chc.conContext.secureRenegotiation) { | 
 | 
                  | 
 | 
                throw chc.conContext.fatal(Alert.HANDSHAKE_FAILURE,  | 
 | 
                        "Inconsistent secure renegotiation indication");  | 
 | 
            } else {     | 
 | 
                if (HandshakeContext.allowUnsafeRenegotiation) { | 
 | 
                    if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { | 
 | 
                        SSLLogger.warning("Using insecure renegotiation"); | 
 | 
                    }  | 
 | 
                } else { | 
 | 
                    // Unsafe renegotiation should have been aborted in  | 
 | 
                      | 
 | 
                    if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { | 
 | 
                        SSLLogger.fine("Terminate insecure renegotiation"); | 
 | 
                    }  | 
 | 
                    throw chc.conContext.fatal(Alert.HANDSHAKE_FAILURE,  | 
 | 
                        "Unsafe renegotiation is not allowed");  | 
 | 
                }  | 
 | 
            }  | 
 | 
        }  | 
 | 
    }  | 
 | 
}  |