1678 lines · 65.9 KB · Java
RawDownload
                        } catch (PrivilegedActionException e) {                            subject = null;                            if (debug != null && Debug.isOn("session")) {                                System.out.println("Attempt to obtain" +                                                " subject failed!");                            }                        }                         if (subject != null) {                            // Eliminate dependency on KerberosPrincipal                            Set<Principal> principals =                                subject.getPrincipals(Principal.class);                            if (!principals.contains(localPrincipal)) {                                resumingSession = false;                                if (debug != null && Debug.isOn("session")) {                                    System.out.println("Subject identity" +                                                        " is not the same");                                }                            } else {                                if (debug != null && Debug.isOn("session"))                                    System.out.println("Subject identity" +                                                        " is same");                            }                        } else {                            resumingSession = false;                            if (debug != null && Debug.isOn("session"))                                System.out.println("Kerberos credentials are" +                                    " not present in the current Subject;" +                                    " check if " +                                    " javax.security.auth.useSubjectAsCreds" +                                    " system property has been set to false");                        }                    }                }                 if (resumingSession) {                    CipherSuite suite = previous.getSuite();                    // verify that the ciphersuite from the cached session                    // is in the list of client requested ciphersuites and                    // we have it enabled                    if ((isNegotiable(suite) == false) ||                            (mesg.getCipherSuites().contains(suite) == false)) {                        resumingSession = false;                    } else {                        // everything looks ok, set the ciphersuite                        // this should be done last when we are sure we                        // will resume                        setCipherSuite(suite);                    }                }                 if (resumingSession) {                    session = previous;                    if (debug != null &&                        (Debug.isOn("handshake") || Debug.isOn("session"))) {                        System.out.println("%% Resuming " + session);                    }                }            }        } // else client did not try to resume         //        // If client hasn't specified a session we can resume, start a        // new one and choose its cipher suite and compression options.        // Unless new session creation is disabled for this connection!        //        if (session == null) {            if (!enableNewSession) {                throw new SSLException("Client did not resume a session");            }             supportedCurves = (SupportedEllipticCurvesExtension)                        mesg.extensions.get(ExtensionType.EXT_ELLIPTIC_CURVES);             // We only need to handle the "signature_algorithm" extension            // for full handshakes and TLS 1.2 or later.            if (protocolVersion.v >= ProtocolVersion.TLS12.v) {                SignatureAlgorithmsExtension signAlgs =                    (SignatureAlgorithmsExtension)mesg.extensions.get(                                    ExtensionType.EXT_SIGNATURE_ALGORITHMS);                if (signAlgs != null) {                    Collection<SignatureAndHashAlgorithm> peerSignAlgs =                                            signAlgs.getSignAlgorithms();                    if (peerSignAlgs == null || peerSignAlgs.isEmpty()) {                        throw new SSLHandshakeException(                            "No peer supported signature algorithms");                    }                     Collection<SignatureAndHashAlgorithm>                        supportedPeerSignAlgs =                            SignatureAndHashAlgorithm.getSupportedAlgorithms(                                                            peerSignAlgs);                    if (supportedPeerSignAlgs.isEmpty()) {                        throw new SSLHandshakeException(                            "No supported signature and hash algorithm " +                            "in common");                    }                     setPeerSupportedSignAlgs(supportedPeerSignAlgs);                } // else, need to use peer implicit supported signature algs            }             session = new SSLSessionImpl(protocolVersion, CipherSuite.C_NULL,                        getLocalSupportedSignAlgs(),                        sslContext.getSecureRandom(),                        getHostAddressSE(), getPortSE());             if (protocolVersion.v >= ProtocolVersion.TLS12.v) {                if (peerSupportedSignAlgs != null) {                    session.setPeerSupportedSignatureAlgorithms(                            peerSupportedSignAlgs);                }   // else, we will set the implicit peer supported signature                    // algorithms in chooseCipherSuite()            }             // set the handshake session            setHandshakeSessionSE(session);             // choose cipher suite and corresponding private key            chooseCipherSuite(mesg);             session.setSuite(cipherSuite);            session.setLocalPrivateKey(privateKey);             // chooseCompression(mesg);        } else {            // set the handshake session            setHandshakeSessionSE(session);        }         if (protocolVersion.v >= ProtocolVersion.TLS12.v) {            if (resumingSession) {                handshakeHash.setCertificateVerifyAlg(null);            }            handshakeHash.setFinishedAlg(cipherSuite.prfAlg.getPRFHashAlg());        }         m1.cipherSuite = cipherSuite;        m1.sessionId = session.getSessionId();        m1.compression_method = session.getCompression();         if (secureRenegotiation) {            // For ServerHellos that are initial handshakes, then the            // "renegotiated_connection" field in "renegotiation_info"            // extension is of zero length.            //            // For ServerHellos that are renegotiating, this field contains            // the concatenation of client_verify_data and server_verify_data.            //            // Note that for initial handshakes, both the clientVerifyData            // variable and serverVerifyData variable are of zero length.            HelloExtension serverHelloRI = new RenegotiationInfoExtension(                                        clientVerifyData, serverVerifyData);            m1.extensions.add(serverHelloRI);        }         if (debug != null && Debug.isOn("handshake")) {            m1.print(System.out);            System.out.println("Cipher suite:  " + session.getSuite());        }        m1.write(output);         //        // If we are resuming a session, we finish writing handshake        // messages right now and then finish.        //        if (resumingSession) {            calculateConnectionKeys(session.getMasterSecret());            sendChangeCipherAndFinish(false);            return;        }          /*         * SECOND, write the server Certificate(s) if we need to.         *         * NOTE:  while an "anonymous RSA" mode is explicitly allowed by         * the protocol, we can't support it since all of the SSL flavors         * defined in the protocol spec are explicitly stated to require         * using RSA certificates.         */        if (keyExchange == K_KRB5 || keyExchange == K_KRB5_EXPORT) {            // Server certificates are omitted for Kerberos ciphers         } else if ((keyExchange != K_DH_ANON) && (keyExchange != K_ECDH_ANON)) {            if (certs == null) {                throw new RuntimeException("no certificates");            }             CertificateMsg m2 = new CertificateMsg(certs);             /*             * Set local certs in the SSLSession, output             * debug info, and then actually write to the client.             */            session.setLocalCertificates(certs);            if (debug != null && Debug.isOn("handshake")) {                m2.print(System.out);            }            m2.write(output);             // XXX has some side effects with OS TCP buffering,            // leave it out for now             // let client verify chain in the meantime...            // output.flush();        } else {            if (certs != null) {                throw new RuntimeException("anonymous keyexchange with certs");            }        }         /*         * THIRD, the ServerKeyExchange message ... iff it's needed.         *         * It's usually needed unless there's an encryption-capable         * RSA cert, or a D-H cert.  The notable exception is that         * exportable ciphers used with big RSA keys need to downgrade         * to use short RSA keys, even when the key/cert encrypts OK.         */         ServerKeyExchange m3;        switch (keyExchange) {        case K_RSA:        case K_KRB5:        case K_KRB5_EXPORT:            // no server key exchange for RSA or KRB5 ciphersuites            m3 = null;            break;        case K_RSA_EXPORT:            if (JsseJce.getRSAKeyLength(certs[0].getPublicKey()) > 512) {                try {                    m3 = new RSA_ServerKeyExchange(                        tempPublicKey, privateKey,                        clnt_random, svr_random,                        sslContext.getSecureRandom());                    privateKey = tempPrivateKey;                } catch (GeneralSecurityException e) {                    throwSSLException                        ("Error generating RSA server key exchange", e);                    m3 = null; // make compiler happy                }            } else {                // RSA_EXPORT with short key, don't need ServerKeyExchange                m3 = null;            }            break;        case K_DHE_RSA:        case K_DHE_DSS:            try {                m3 = new DH_ServerKeyExchange(dh,                    privateKey,                    clnt_random.random_bytes,                    svr_random.random_bytes,                    sslContext.getSecureRandom(),                    preferableSignatureAlgorithm,                    protocolVersion);            } catch (GeneralSecurityException e) {                throwSSLException("Error generating DH server key exchange", e);                m3 = null; // make compiler happy            }            break;        case K_DH_ANON:            m3 = new DH_ServerKeyExchange(dh, protocolVersion);            break;        case K_ECDHE_RSA:        case K_ECDHE_ECDSA:        case K_ECDH_ANON:            try {                m3 = new ECDH_ServerKeyExchange(ecdh,                    privateKey,                    clnt_random.random_bytes,                    svr_random.random_bytes,                    sslContext.getSecureRandom(),                    preferableSignatureAlgorithm,                    protocolVersion);            } catch (GeneralSecurityException e) {                throwSSLException(                    "Error generating ECDH server key exchange", e);                m3 = null; // make compiler happy            }            break;        case K_ECDH_RSA:        case K_ECDH_ECDSA:            // ServerKeyExchange not used for fixed ECDH            m3 = null;            break;        default:            throw new RuntimeException("internal error: " + keyExchange);        }        if (m3 != null) {            if (debug != null && Debug.isOn("handshake")) {                m3.print(System.out);            }            m3.write(output);        }         //        // FOURTH, the CertificateRequest message.  The details of        // the message can be affected by the key exchange algorithm        // in use.  For example, certs with fixed Diffie-Hellman keys        // are only useful with the DH_DSS and DH_RSA key exchange        // algorithms.        //        // Needed only if server requires client to authenticate self.        // Illegal for anonymous flavors, so we need to check that.        //        // CertificateRequest is omitted for Kerberos ciphers        if (doClientAuth != SSLEngineImpl.clauth_none &&                keyExchange != K_DH_ANON && keyExchange != K_ECDH_ANON &&                keyExchange != K_KRB5 && keyExchange != K_KRB5_EXPORT) {             CertificateRequest m4;            X509Certificate caCerts[];             Collection<SignatureAndHashAlgorithm> localSignAlgs = null;            if (protocolVersion.v >= ProtocolVersion.TLS12.v) {                // We currently use all local upported signature and hash                // algorithms. However, to minimize the computation cost                // of requested hash algorithms, we may use a restricted                // set of signature algorithms in the future.                localSignAlgs = getLocalSupportedSignAlgs();                if (localSignAlgs.isEmpty()) {                    throw new SSLHandshakeException(                            "No supported signature algorithm");                }                 Set<String> localHashAlgs =                    SignatureAndHashAlgorithm.getHashAlgorithmNames(                        localSignAlgs);                if (localHashAlgs.isEmpty()) {                    throw new SSLHandshakeException(                            "No supported signature algorithm");                }                handshakeHash.restrictCertificateVerifyAlgs(localHashAlgs);            }             caCerts = sslContext.getX509TrustManager().getAcceptedIssuers();            m4 = new CertificateRequest(caCerts, keyExchange,                                            localSignAlgs, protocolVersion);             if (debug != null && Debug.isOn("handshake")) {                m4.print(System.out);            }            m4.write(output);        } else {            if (protocolVersion.v >= ProtocolVersion.TLS12.v) {                handshakeHash.setCertificateVerifyAlg(null);            }        }         /*         * FIFTH, say ServerHelloDone.         */        ServerHelloDone m5 = new ServerHelloDone();         if (debug != null && Debug.isOn("handshake")) {            m5.print(System.out);        }        m5.write(output);         /*         * Flush any buffered messages so the client will see them.         * Ideally, all the messages above go in a single network level         * message to the client.  Without big Certificate chains, it's         * going to be the common case.         */        output.flush();    }     /*     * Choose cipher suite from among those supported by client. Sets     * the cipherSuite and keyExchange variables.     */    private void chooseCipherSuite(ClientHello mesg) throws IOException {        for (CipherSuite suite : mesg.getCipherSuites().collection()) {            if (isNegotiable(suite) == false) {                continue;            }             if (doClientAuth == SSLEngineImpl.clauth_required) {                if ((suite.keyExchange == K_DH_ANON) ||                    (suite.keyExchange == K_ECDH_ANON)) {                    continue;                }            }            if (trySetCipherSuite(suite) == false) {                continue;            }            return;        }        fatalSE(Alerts.alert_handshake_failure,                    "no cipher suites in common");    }     /**     * Set the given CipherSuite, if possible. Return the result.     * The call succeeds if the CipherSuite is available and we have     * the necessary certificates to complete the handshake. We don't     * check if the CipherSuite is actually enabled.     *     * If successful, this method also generates ephemeral keys if     * required for this ciphersuite. This may take some time, so this     * method should only be called if you really want to use the     * CipherSuite.     *     * This method is called from chooseCipherSuite() in this class.     */    boolean trySetCipherSuite(CipherSuite suite) {        /*         * If we're resuming a session we know we can         * support this key exchange algorithm and in fact         * have already cached the result of it in         * the session state.         */        if (resumingSession) {            return true;        }         if (suite.isNegotiable() == false) {            return false;        }         // must not negotiate the obsoleted weak cipher suites.        if (protocolVersion.v >= suite.obsoleted) {            return false;        }         // must not negotiate unsupported cipher suites.        if (protocolVersion.v < suite.supported) {            return false;        }         KeyExchange keyExchange = suite.keyExchange;         // null out any existing references        privateKey = null;        certs = null;        dh = null;        tempPrivateKey = null;        tempPublicKey = null;         Collection<SignatureAndHashAlgorithm> supportedSignAlgs = null;        if (protocolVersion.v >= ProtocolVersion.TLS12.v) {            if (peerSupportedSignAlgs != null) {                supportedSignAlgs = peerSupportedSignAlgs;            } else {                SignatureAndHashAlgorithm algorithm = null;                 // we may optimize the performance                switch (keyExchange) {                    // If the negotiated key exchange algorithm is one of                    // (RSA, DHE_RSA, DH_RSA, RSA_PSK, ECDH_RSA, ECDHE_RSA),                    // behave as if client had sent the value {sha1,rsa}.                    case K_RSA:                    case K_DHE_RSA:                    case K_DH_RSA:                    // case K_RSA_PSK:                    case K_ECDH_RSA:                    case K_ECDHE_RSA:                        algorithm = SignatureAndHashAlgorithm.valueOf(                                HashAlgorithm.SHA1.value,                                SignatureAlgorithm.RSA.value, 0);                        break;                    // If the negotiated key exchange algorithm is one of                    // (DHE_DSS, DH_DSS), behave as if the client had                    // sent the value {sha1,dsa}.                    case K_DHE_DSS:                    case K_DH_DSS:                        algorithm = SignatureAndHashAlgorithm.valueOf(                                HashAlgorithm.SHA1.value,                                SignatureAlgorithm.DSA.value, 0);                        break;                    // If the negotiated key exchange algorithm is one of                    // (ECDH_ECDSA, ECDHE_ECDSA), behave as if the client                    // had sent value {sha1,ecdsa}.                    case K_ECDH_ECDSA:                    case K_ECDHE_ECDSA:                        algorithm = SignatureAndHashAlgorithm.valueOf(                                HashAlgorithm.SHA1.value,                                SignatureAlgorithm.ECDSA.value, 0);                        break;                    default:                        // no peer supported signature algorithms                }                 if (algorithm == null) {                    supportedSignAlgs =                        Collections.<SignatureAndHashAlgorithm>emptySet();                } else {                    supportedSignAlgs =                        new ArrayList<SignatureAndHashAlgorithm>(1);                    supportedSignAlgs.add(algorithm);                }                 // Sets the peer supported signature algorithm to use in KM                // temporarily.                session.setPeerSupportedSignatureAlgorithms(supportedSignAlgs);            }        }

Lines 501–1000 of 1678. Previous lines