"%% Cached server session: " + session); } } else if (!resumingSession && debug != null && Debug.isOn("session")) { System.out.println( "%% Didn't cache non-resumable server session: " + session); } } /* * Compute finished message with the "server" digest (and then forget * about that digest, it can't be used again). */ private void sendChangeCipherAndFinish(boolean finishedTag) throws IOException { output.flush(); Finished mesg = new Finished(protocolVersion, handshakeHash, Finished.SERVER, session.getMasterSecret(), cipherSuite); /* * Send the change_cipher_spec record; then our Finished handshake * message will be the last handshake message. Flush, and now we * are ready for application data!! */ sendChangeCipherSpec(mesg, finishedTag); /* * save server verify data for secure renegotiation */ if (secureRenegotiation) { serverVerifyData = mesg.getVerifyData(); } /* * Update state machine so client MUST send 'finished' next * The update should only take place if it is not in the fast * handshake mode since the server has to wait for a finished * message from the client. */ if (finishedTag) { state = HandshakeMessage.ht_finished; } } /* * Returns a HelloRequest message to kickstart renegotiations */ HandshakeMessage getKickstartMessage() { return new HelloRequest(); } /* * Fault detected during handshake. */ void handshakeAlert(byte description) throws SSLProtocolException { String message = Alerts.alertDescription(description); if (debug != null && Debug.isOn("handshake")) { System.out.println("SSL -- handshake alert: " + message); } /* * It's ok to get a no_certificate alert from a client of which * we *requested* authentication information. * However, if we *required* it, then this is not acceptable. * * Anyone calling getPeerCertificates() on the * session will get an SSLPeerUnverifiedException. */ if ((description == Alerts.alert_no_certificate) && (doClientAuth == SSLEngineImpl.clauth_requested)) { return; } throw new SSLProtocolException("handshake alert: " + message); } /* * RSA key exchange is normally used. The client encrypts a "pre-master * secret" with the server's public key, from the Certificate (or else * ServerKeyExchange) message that was sent to it by the server. That's * decrypted using the private key before we get here. */ private SecretKey clientKeyExchange(RSAClientKeyExchange mesg) throws IOException { if (debug != null && Debug.isOn("handshake")) { mesg.print(System.out); } return mesg.preMaster; } /* * Verify the certificate sent by the client. We'll only get one if we * sent a CertificateRequest to request client authentication. If we * are in TLS mode, the client may send a message with no certificates * to indicate it does not have an appropriate chain. (In SSLv3 mode, * it would send a no certificate alert). */ private void clientCertificate(CertificateMsg mesg) throws IOException { if (debug != null && Debug.isOn("handshake")) { mesg.print(System.out); } X509Certificate[] peerCerts = mesg.getCertificateChain(); if (peerCerts.length == 0) { /* * If the client authentication is only *REQUESTED* (e.g. * not *REQUIRED*, this is an acceptable condition.) */ if (doClientAuth == SSLEngineImpl.clauth_requested) { // Smart (aka stupid) to forecast that no CertificateVerify // message will be received. if (protocolVersion.v >= ProtocolVersion.TLS12.v) { handshakeHash.setCertificateVerifyAlg(null); } return; } else { fatalSE(Alerts.alert_bad_certificate, "null cert chain"); } } // ask the trust manager to verify the chain X509TrustManager tm = sslContext.getX509TrustManager(); try { // find out the types of client authentication used PublicKey key = peerCerts[0].getPublicKey(); String keyAlgorithm = key.getAlgorithm(); String authType; if (keyAlgorithm.equals("RSA")) { authType = "RSA"; } else if (keyAlgorithm.equals("DSA")) { authType = "DSA"; } else if (keyAlgorithm.equals("EC")) { authType = "EC"; } else { // unknown public key type authType = "UNKNOWN"; } if (tm instanceof X509ExtendedTrustManager) { if (conn != null) { ((X509ExtendedTrustManager)tm).checkClientTrusted( peerCerts.clone(), authType, conn); } else { ((X509ExtendedTrustManager)tm).checkClientTrusted( peerCerts.clone(), authType, engine); } } else { // Unlikely to happen, because we have wrapped the old // X509TrustManager with the new X509ExtendedTrustManager. throw new CertificateException( "Improper X509TrustManager implementation"); } } catch (CertificateException e) { // This will throw an exception, so include the original error. fatalSE(Alerts.alert_certificate_unknown, e); } // set the flag for clientCertificateVerify message needClientVerify = true; session.setPeerCertificates(peerCerts); }}Lines 1501–1678 of 1678. Previous lines
"%% Cached server session: " + session); } } else if (!resumingSession && debug != null && Debug.isOn("session")) { System.out.println( "%% Didn't cache non-resumable server session: " + session); } } /* * Compute finished message with the "server" digest (and then forget * about that digest, it can't be used again). */ private void sendChangeCipherAndFinish(boolean finishedTag) throws IOException { output.flush(); Finished mesg = new Finished(protocolVersion, handshakeHash, Finished.SERVER, session.getMasterSecret(), cipherSuite); /* * Send the change_cipher_spec record; then our Finished handshake * message will be the last handshake message. Flush, and now we * are ready for application data!! */ sendChangeCipherSpec(mesg, finishedTag); /* * save server verify data for secure renegotiation */ if (secureRenegotiation) { serverVerifyData = mesg.getVerifyData(); } /* * Update state machine so client MUST send 'finished' next * The update should only take place if it is not in the fast * handshake mode since the server has to wait for a finished * message from the client. */ if (finishedTag) { state = HandshakeMessage.ht_finished; } } /* * Returns a HelloRequest message to kickstart renegotiations */ HandshakeMessage getKickstartMessage() { return new HelloRequest(); } /* * Fault detected during handshake. */ void handshakeAlert(byte description) throws SSLProtocolException { String message = Alerts.alertDescription(description); if (debug != null && Debug.isOn("handshake")) { System.out.println("SSL -- handshake alert: " + message); } /* * It's ok to get a no_certificate alert from a client of which * we *requested* authentication information. * However, if we *required* it, then this is not acceptable. * * Anyone calling getPeerCertificates() on the * session will get an SSLPeerUnverifiedException. */ if ((description == Alerts.alert_no_certificate) && (doClientAuth == SSLEngineImpl.clauth_requested)) { return; } throw new SSLProtocolException("handshake alert: " + message); } /* * RSA key exchange is normally used. The client encrypts a "pre-master * secret" with the server's public key, from the Certificate (or else * ServerKeyExchange) message that was sent to it by the server. That's * decrypted using the private key before we get here. */ private SecretKey clientKeyExchange(RSAClientKeyExchange mesg) throws IOException { if (debug != null && Debug.isOn("handshake")) { mesg.print(System.out); } return mesg.preMaster; } /* * Verify the certificate sent by the client. We'll only get one if we * sent a CertificateRequest to request client authentication. If we * are in TLS mode, the client may send a message with no certificates * to indicate it does not have an appropriate chain. (In SSLv3 mode, * it would send a no certificate alert). */ private void clientCertificate(CertificateMsg mesg) throws IOException { if (debug != null && Debug.isOn("handshake")) { mesg.print(System.out); } X509Certificate[] peerCerts = mesg.getCertificateChain(); if (peerCerts.length == 0) { /* * If the client authentication is only *REQUESTED* (e.g. * not *REQUIRED*, this is an acceptable condition.) */ if (doClientAuth == SSLEngineImpl.clauth_requested) { // Smart (aka stupid) to forecast that no CertificateVerify // message will be received. if (protocolVersion.v >= ProtocolVersion.TLS12.v) { handshakeHash.setCertificateVerifyAlg(null); } return; } else { fatalSE(Alerts.alert_bad_certificate, "null cert chain"); } } // ask the trust manager to verify the chain X509TrustManager tm = sslContext.getX509TrustManager(); try { // find out the types of client authentication used PublicKey key = peerCerts[0].getPublicKey(); String keyAlgorithm = key.getAlgorithm(); String authType; if (keyAlgorithm.equals("RSA")) { authType = "RSA"; } else if (keyAlgorithm.equals("DSA")) { authType = "DSA"; } else if (keyAlgorithm.equals("EC")) { authType = "EC"; } else { // unknown public key type authType = "UNKNOWN"; } if (tm instanceof X509ExtendedTrustManager) { if (conn != null) { ((X509ExtendedTrustManager)tm).checkClientTrusted( peerCerts.clone(), authType, conn); } else { ((X509ExtendedTrustManager)tm).checkClientTrusted( peerCerts.clone(), authType, engine); } } else { // Unlikely to happen, because we have wrapped the old // X509TrustManager with the new X509ExtendedTrustManager. throw new CertificateException( "Improper X509TrustManager implementation"); } } catch (CertificateException e) { // This will throw an exception, so include the original error. fatalSE(Alerts.alert_certificate_unknown, e); } // set the flag for clientCertificateVerify message needClientVerify = true; session.setPeerCertificates(peerCerts); } }