jdk/src/share/classes/sun/security/ssl/ServerHandshaker.java
author weijun
Tue, 09 Jun 2009 14:17:05 +0800
changeset 2942 37d9baeb7518
parent 2 90ce3da70b43
child 4236 02f52c723b79
permissions -rw-r--r--
6578647: Undefined requesting URL in java.net.Authenticator.getPasswordAuthentication() Reviewed-by: chegar, valeriep
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     1
/*
2942
37d9baeb7518 6578647: Undefined requesting URL in java.net.Authenticator.getPasswordAuthentication()
weijun
parents: 2
diff changeset
     2
 * Copyright 1996-2009 Sun Microsystems, Inc.  All Rights Reserved.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
90ce3da70b43 Initial load
duke
parents:
diff changeset
     4
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
90ce3da70b43 Initial load
duke
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
90ce3da70b43 Initial load
duke
parents:
diff changeset
     7
 * published by the Free Software Foundation.  Sun designates this
90ce3da70b43 Initial load
duke
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
90ce3da70b43 Initial load
duke
parents:
diff changeset
     9
 * by Sun in the LICENSE file that accompanied this code.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    10
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
90ce3da70b43 Initial load
duke
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
90ce3da70b43 Initial load
duke
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
90ce3da70b43 Initial load
duke
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
90ce3da70b43 Initial load
duke
parents:
diff changeset
    15
 * accompanied this code).
90ce3da70b43 Initial load
duke
parents:
diff changeset
    16
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
90ce3da70b43 Initial load
duke
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    20
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    21
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    22
 * CA 95054 USA or visit www.sun.com if you need additional information or
90ce3da70b43 Initial load
duke
parents:
diff changeset
    23
 * have any questions.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    24
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    25
90ce3da70b43 Initial load
duke
parents:
diff changeset
    26
90ce3da70b43 Initial load
duke
parents:
diff changeset
    27
package sun.security.ssl;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    28
90ce3da70b43 Initial load
duke
parents:
diff changeset
    29
import java.io.*;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    30
import java.util.*;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    31
import java.security.*;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    32
import java.security.cert.*;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    33
import java.security.interfaces.*;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    34
import java.security.spec.ECParameterSpec;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    35
90ce3da70b43 Initial load
duke
parents:
diff changeset
    36
import javax.crypto.SecretKey;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    37
import javax.crypto.spec.SecretKeySpec;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    38
90ce3da70b43 Initial load
duke
parents:
diff changeset
    39
import javax.net.ssl.*;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    40
90ce3da70b43 Initial load
duke
parents:
diff changeset
    41
import javax.security.auth.Subject;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    42
import javax.security.auth.kerberos.KerberosKey;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    43
import javax.security.auth.kerberos.KerberosPrincipal;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    44
import javax.security.auth.kerberos.ServicePermission;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    45
import sun.security.jgss.krb5.Krb5Util;
2942
37d9baeb7518 6578647: Undefined requesting URL in java.net.Authenticator.getPasswordAuthentication()
weijun
parents: 2
diff changeset
    46
import sun.security.jgss.GSSCaller;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    47
90ce3da70b43 Initial load
duke
parents:
diff changeset
    48
import com.sun.net.ssl.internal.ssl.X509ExtendedTrustManager;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    49
90ce3da70b43 Initial load
duke
parents:
diff changeset
    50
import sun.security.ssl.HandshakeMessage.*;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    51
import sun.security.ssl.CipherSuite.*;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    52
import static sun.security.ssl.CipherSuite.*;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    53
import static sun.security.ssl.CipherSuite.KeyExchange.*;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    54
90ce3da70b43 Initial load
duke
parents:
diff changeset
    55
/**
90ce3da70b43 Initial load
duke
parents:
diff changeset
    56
 * ServerHandshaker does the protocol handshaking from the point
90ce3da70b43 Initial load
duke
parents:
diff changeset
    57
 * of view of a server.  It is driven asychronously by handshake messages
90ce3da70b43 Initial load
duke
parents:
diff changeset
    58
 * as delivered by the parent Handshaker class, and also uses
90ce3da70b43 Initial load
duke
parents:
diff changeset
    59
 * common functionality (e.g. key generation) that is provided there.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    60
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    61
 * @author David Brownell
90ce3da70b43 Initial load
duke
parents:
diff changeset
    62
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    63
final class ServerHandshaker extends Handshaker {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    64
90ce3da70b43 Initial load
duke
parents:
diff changeset
    65
    // is the server going to require the client to authenticate?
90ce3da70b43 Initial load
duke
parents:
diff changeset
    66
    private byte                doClientAuth;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    67
90ce3da70b43 Initial load
duke
parents:
diff changeset
    68
    // our authentication info
90ce3da70b43 Initial load
duke
parents:
diff changeset
    69
    private X509Certificate[]   certs;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    70
    private PrivateKey          privateKey;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    71
90ce3da70b43 Initial load
duke
parents:
diff changeset
    72
    private KerberosKey[]       kerberosKeys;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    73
90ce3da70b43 Initial load
duke
parents:
diff changeset
    74
    // flag to check for clientCertificateVerify message
90ce3da70b43 Initial load
duke
parents:
diff changeset
    75
    private boolean             needClientVerify = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    76
90ce3da70b43 Initial load
duke
parents:
diff changeset
    77
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
    78
     * For exportable ciphersuites using non-exportable key sizes, we use
90ce3da70b43 Initial load
duke
parents:
diff changeset
    79
     * ephemeral RSA keys. We could also do anonymous RSA in the same way
90ce3da70b43 Initial load
duke
parents:
diff changeset
    80
     * but there are no such ciphersuites currently defined.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    81
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    82
    private PrivateKey          tempPrivateKey;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    83
    private PublicKey           tempPublicKey;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    84
90ce3da70b43 Initial load
duke
parents:
diff changeset
    85
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
    86
     * For anonymous and ephemeral Diffie-Hellman key exchange, we use
90ce3da70b43 Initial load
duke
parents:
diff changeset
    87
     * ephemeral Diffie-Hellman keys.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    88
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    89
    private DHCrypt dh;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    90
90ce3da70b43 Initial load
duke
parents:
diff changeset
    91
    // Helper for ECDH based key exchanges
90ce3da70b43 Initial load
duke
parents:
diff changeset
    92
    private ECDHCrypt ecdh;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    93
90ce3da70b43 Initial load
duke
parents:
diff changeset
    94
    // version request by the client in its ClientHello
90ce3da70b43 Initial load
duke
parents:
diff changeset
    95
    // we remember it for the RSA premaster secret version check
90ce3da70b43 Initial load
duke
parents:
diff changeset
    96
    private ProtocolVersion clientRequestedVersion;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    97
90ce3da70b43 Initial load
duke
parents:
diff changeset
    98
    private SupportedEllipticCurvesExtension supportedCurves;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    99
90ce3da70b43 Initial load
duke
parents:
diff changeset
   100
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   101
     * Constructor ... use the keys found in the auth context.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   102
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   103
    ServerHandshaker(SSLSocketImpl socket, SSLContextImpl context,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   104
            ProtocolList enabledProtocols, byte clientAuth) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   105
        super(socket, context, enabledProtocols,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   106
                        (clientAuth != SSLEngineImpl.clauth_none), false);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   107
        doClientAuth = clientAuth;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   108
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   109
90ce3da70b43 Initial load
duke
parents:
diff changeset
   110
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   111
     * Constructor ... use the keys found in the auth context.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   112
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   113
    ServerHandshaker(SSLEngineImpl engine, SSLContextImpl context,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   114
            ProtocolList enabledProtocols, byte clientAuth) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   115
        super(engine, context, enabledProtocols,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   116
                        (clientAuth != SSLEngineImpl.clauth_none), false);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   117
        doClientAuth = clientAuth;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   118
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   119
90ce3da70b43 Initial load
duke
parents:
diff changeset
   120
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   121
     * As long as handshaking has not started, we can change
90ce3da70b43 Initial load
duke
parents:
diff changeset
   122
     * whether client authentication is required.  Otherwise,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   123
     * we will need to wait for the next handshake.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   124
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   125
    void setClientAuth(byte clientAuth) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   126
        doClientAuth = clientAuth;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   127
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   128
90ce3da70b43 Initial load
duke
parents:
diff changeset
   129
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   130
     * This routine handles all the server side handshake messages, one at
90ce3da70b43 Initial load
duke
parents:
diff changeset
   131
     * a time.  Given the message type (and in some cases the pending cipher
90ce3da70b43 Initial load
duke
parents:
diff changeset
   132
     * spec) it parses the type-specific message.  Then it calls a function
90ce3da70b43 Initial load
duke
parents:
diff changeset
   133
     * that handles that specific message.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   134
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   135
     * It updates the state machine as each message is processed, and writes
90ce3da70b43 Initial load
duke
parents:
diff changeset
   136
     * responses as needed using the connection in the constructor.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   137
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   138
    void processMessage(byte type, int message_len)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   139
            throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   140
        //
90ce3da70b43 Initial load
duke
parents:
diff changeset
   141
        // In SSLv3 and TLS, messages follow strictly increasing
90ce3da70b43 Initial load
duke
parents:
diff changeset
   142
        // numerical order _except_ for one annoying special case.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   143
        //
90ce3da70b43 Initial load
duke
parents:
diff changeset
   144
        if ((state > type)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   145
                && (state != HandshakeMessage.ht_client_key_exchange
90ce3da70b43 Initial load
duke
parents:
diff changeset
   146
                    && type != HandshakeMessage.ht_certificate_verify)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   147
            throw new SSLProtocolException(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   148
                    "Handshake message sequence violation, state = " + state
90ce3da70b43 Initial load
duke
parents:
diff changeset
   149
                    + ", type = " + type);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   150
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   151
90ce3da70b43 Initial load
duke
parents:
diff changeset
   152
        switch (type) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   153
            case HandshakeMessage.ht_client_hello:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   154
                ClientHello ch = new ClientHello(input, message_len);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   155
                /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   156
                 * send it off for processing.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   157
                 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   158
                this.clientHello(ch);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   159
                break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   160
90ce3da70b43 Initial load
duke
parents:
diff changeset
   161
            case HandshakeMessage.ht_certificate:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   162
                if (doClientAuth == SSLEngineImpl.clauth_none) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   163
                    fatalSE(Alerts.alert_unexpected_message,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   164
                                "client sent unsolicited cert chain");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   165
                    // NOTREACHED
90ce3da70b43 Initial load
duke
parents:
diff changeset
   166
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   167
                this.clientCertificate(new CertificateMsg(input));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   168
                break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   169
90ce3da70b43 Initial load
duke
parents:
diff changeset
   170
            case HandshakeMessage.ht_client_key_exchange:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   171
                SecretKey preMasterSecret;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   172
                switch (keyExchange) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   173
                case K_RSA:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   174
                case K_RSA_EXPORT:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   175
                    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   176
                     * The client's pre-master secret is decrypted using
90ce3da70b43 Initial load
duke
parents:
diff changeset
   177
                     * either the server's normal private RSA key, or the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   178
                     * temporary one used for non-export or signing-only
90ce3da70b43 Initial load
duke
parents:
diff changeset
   179
                     * certificates/keys.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   180
                     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   181
                    RSAClientKeyExchange pms = new RSAClientKeyExchange
90ce3da70b43 Initial load
duke
parents:
diff changeset
   182
                        (protocolVersion, input, message_len, privateKey);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   183
                    preMasterSecret = this.clientKeyExchange(pms);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   184
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   185
                case K_KRB5:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   186
                case K_KRB5_EXPORT:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   187
                    preMasterSecret = this.clientKeyExchange(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   188
                        new KerberosClientKeyExchange(protocolVersion,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   189
                            clientRequestedVersion,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   190
                            sslContext.getSecureRandom(),
90ce3da70b43 Initial load
duke
parents:
diff changeset
   191
                            input,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   192
                            kerberosKeys));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   193
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   194
                case K_DHE_RSA:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   195
                case K_DHE_DSS:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   196
                case K_DH_ANON:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   197
                    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   198
                     * The pre-master secret is derived using the normal
90ce3da70b43 Initial load
duke
parents:
diff changeset
   199
                     * Diffie-Hellman calculation.   Note that the main
90ce3da70b43 Initial load
duke
parents:
diff changeset
   200
                     * protocol difference in these five flavors is in how
90ce3da70b43 Initial load
duke
parents:
diff changeset
   201
                     * the ServerKeyExchange message was constructed!
90ce3da70b43 Initial load
duke
parents:
diff changeset
   202
                     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   203
                    preMasterSecret = this.clientKeyExchange(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   204
                            new DHClientKeyExchange(input));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   205
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   206
                case K_ECDH_RSA:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   207
                case K_ECDH_ECDSA:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   208
                case K_ECDHE_RSA:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   209
                case K_ECDHE_ECDSA:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   210
                case K_ECDH_ANON:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   211
                    preMasterSecret = this.clientKeyExchange
90ce3da70b43 Initial load
duke
parents:
diff changeset
   212
                                            (new ECDHClientKeyExchange(input));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   213
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   214
                default:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   215
                    throw new SSLProtocolException
90ce3da70b43 Initial load
duke
parents:
diff changeset
   216
                        ("Unrecognized key exchange: " + keyExchange);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   217
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   218
90ce3da70b43 Initial load
duke
parents:
diff changeset
   219
                //
90ce3da70b43 Initial load
duke
parents:
diff changeset
   220
                // All keys are calculated from the premaster secret
90ce3da70b43 Initial load
duke
parents:
diff changeset
   221
                // and the exchanged nonces in the same way.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   222
                //
90ce3da70b43 Initial load
duke
parents:
diff changeset
   223
                calculateKeys(preMasterSecret, clientRequestedVersion);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   224
                break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   225
90ce3da70b43 Initial load
duke
parents:
diff changeset
   226
            case HandshakeMessage.ht_certificate_verify:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   227
                this.clientCertificateVerify(new CertificateVerify(input));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   228
                break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   229
90ce3da70b43 Initial load
duke
parents:
diff changeset
   230
            case HandshakeMessage.ht_finished:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   231
                this.clientFinished(new Finished(protocolVersion, input));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   232
                break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   233
90ce3da70b43 Initial load
duke
parents:
diff changeset
   234
            default:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   235
                throw new SSLProtocolException(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   236
                        "Illegal server handshake msg, " + type);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   237
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   238
90ce3da70b43 Initial load
duke
parents:
diff changeset
   239
        //
90ce3da70b43 Initial load
duke
parents:
diff changeset
   240
        // Move the state machine forward except for that annoying
90ce3da70b43 Initial load
duke
parents:
diff changeset
   241
        // special case.  This means that clients could send extra
90ce3da70b43 Initial load
duke
parents:
diff changeset
   242
        // cert verify messages; not a problem so long as all of
90ce3da70b43 Initial load
duke
parents:
diff changeset
   243
        // them actually check out.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   244
        //
90ce3da70b43 Initial load
duke
parents:
diff changeset
   245
        if (state < type && type != HandshakeMessage.ht_certificate_verify) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   246
            state = type;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   247
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   248
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   249
90ce3da70b43 Initial load
duke
parents:
diff changeset
   250
90ce3da70b43 Initial load
duke
parents:
diff changeset
   251
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   252
     * ClientHello presents the server with a bunch of options, to which the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   253
     * server replies with a ServerHello listing the ones which this session
90ce3da70b43 Initial load
duke
parents:
diff changeset
   254
     * will use.  If needed, it also writes its Certificate plus in some cases
90ce3da70b43 Initial load
duke
parents:
diff changeset
   255
     * a ServerKeyExchange message.  It may also write a CertificateRequest,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   256
     * to elicit a client certificate.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   257
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   258
     * All these messages are terminated by a ServerHelloDone message.  In
90ce3da70b43 Initial load
duke
parents:
diff changeset
   259
     * most cases, all this can be sent in a single Record.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   260
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   261
    private void clientHello(ClientHello mesg) throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   262
        if (debug != null && Debug.isOn("handshake")) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   263
            mesg.print(System.out);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   264
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   265
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   266
         * Always make sure this entire record has been digested before we
90ce3da70b43 Initial load
duke
parents:
diff changeset
   267
         * start emitting output, to ensure correct digesting order.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   268
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   269
        input.digestNow();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   270
90ce3da70b43 Initial load
duke
parents:
diff changeset
   271
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   272
         * FIRST, construct the ServerHello using the options and priorities
90ce3da70b43 Initial load
duke
parents:
diff changeset
   273
         * from the ClientHello.  Update the (pending) cipher spec as we do
90ce3da70b43 Initial load
duke
parents:
diff changeset
   274
         * so, and save the client's version to protect against rollback
90ce3da70b43 Initial load
duke
parents:
diff changeset
   275
         * attacks.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   276
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   277
         * There are a bunch of minor tasks here, and one major one: deciding
90ce3da70b43 Initial load
duke
parents:
diff changeset
   278
         * if the short or the full handshake sequence will be used.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   279
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   280
        ServerHello m1 = new ServerHello();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   281
90ce3da70b43 Initial load
duke
parents:
diff changeset
   282
        clientRequestedVersion = mesg.protocolVersion;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   283
90ce3da70b43 Initial load
duke
parents:
diff changeset
   284
        // check if clientVersion is recent enough for us
90ce3da70b43 Initial load
duke
parents:
diff changeset
   285
        if (clientRequestedVersion.v < enabledProtocols.min.v) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   286
            fatalSE(Alerts.alert_handshake_failure,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   287
                "Client requested protocol " + clientRequestedVersion +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   288
                 " not enabled or not supported");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   289
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   290
90ce3da70b43 Initial load
duke
parents:
diff changeset
   291
        // now we know we have an acceptable version
90ce3da70b43 Initial load
duke
parents:
diff changeset
   292
        // use the lower of our max and the client requested version
90ce3da70b43 Initial load
duke
parents:
diff changeset
   293
        ProtocolVersion selectedVersion;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   294
        if (clientRequestedVersion.v <= enabledProtocols.max.v) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   295
            selectedVersion = clientRequestedVersion;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   296
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   297
            selectedVersion = enabledProtocols.max;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   298
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   299
        setVersion(selectedVersion);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   300
90ce3da70b43 Initial load
duke
parents:
diff changeset
   301
        m1.protocolVersion = protocolVersion;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   302
90ce3da70b43 Initial load
duke
parents:
diff changeset
   303
        //
90ce3da70b43 Initial load
duke
parents:
diff changeset
   304
        // random ... save client and server values for later use
90ce3da70b43 Initial load
duke
parents:
diff changeset
   305
        // in computing the master secret (from pre-master secret)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   306
        // and thence the other crypto keys.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   307
        //
90ce3da70b43 Initial load
duke
parents:
diff changeset
   308
        // NOTE:  this use of three inputs to generating _each_ set
90ce3da70b43 Initial load
duke
parents:
diff changeset
   309
        // of ciphers slows things down, but it does increase the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   310
        // security since each connection in the session can hold
90ce3da70b43 Initial load
duke
parents:
diff changeset
   311
        // its own authenticated (and strong) keys.  One could make
90ce3da70b43 Initial load
duke
parents:
diff changeset
   312
        // creation of a session a rare thing...
90ce3da70b43 Initial load
duke
parents:
diff changeset
   313
        //
90ce3da70b43 Initial load
duke
parents:
diff changeset
   314
        clnt_random = mesg.clnt_random;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   315
        svr_random = new RandomCookie(sslContext.getSecureRandom());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   316
        m1.svr_random = svr_random;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   317
90ce3da70b43 Initial load
duke
parents:
diff changeset
   318
        session = null; // forget about the current session
90ce3da70b43 Initial load
duke
parents:
diff changeset
   319
        //
90ce3da70b43 Initial load
duke
parents:
diff changeset
   320
        // Here we go down either of two paths:  (a) the fast one, where
90ce3da70b43 Initial load
duke
parents:
diff changeset
   321
        // the client's asked to rejoin an existing session, and the server
90ce3da70b43 Initial load
duke
parents:
diff changeset
   322
        // permits this; (b) the other one, where a new session is created.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   323
        //
90ce3da70b43 Initial load
duke
parents:
diff changeset
   324
        if (mesg.sessionId.length() != 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   325
            // client is trying to resume a session, let's see...
90ce3da70b43 Initial load
duke
parents:
diff changeset
   326
90ce3da70b43 Initial load
duke
parents:
diff changeset
   327
            SSLSessionImpl previous = ((SSLSessionContextImpl)sslContext
90ce3da70b43 Initial load
duke
parents:
diff changeset
   328
                        .engineGetServerSessionContext())
90ce3da70b43 Initial load
duke
parents:
diff changeset
   329
                        .get(mesg.sessionId.getId());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   330
            //
90ce3da70b43 Initial load
duke
parents:
diff changeset
   331
            // Check if we can use the fast path, resuming a session.  We
90ce3da70b43 Initial load
duke
parents:
diff changeset
   332
            // can do so iff we have a valid record for that session, and
90ce3da70b43 Initial load
duke
parents:
diff changeset
   333
            // the cipher suite for that session was on the list which the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   334
            // client requested, and if we're not forgetting any needed
90ce3da70b43 Initial load
duke
parents:
diff changeset
   335
            // authentication on the part of the client.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   336
            //
90ce3da70b43 Initial load
duke
parents:
diff changeset
   337
            if (previous != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   338
                resumingSession = previous.isRejoinable();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   339
90ce3da70b43 Initial load
duke
parents:
diff changeset
   340
                if (resumingSession) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   341
                    ProtocolVersion oldVersion = previous.getProtocolVersion();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   342
                    // cannot resume session with different version
90ce3da70b43 Initial load
duke
parents:
diff changeset
   343
                    if (oldVersion != protocolVersion) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   344
                        resumingSession = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   345
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   346
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   347
90ce3da70b43 Initial load
duke
parents:
diff changeset
   348
                if (resumingSession &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   349
                        (doClientAuth == SSLEngineImpl.clauth_required)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   350
                    try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   351
                        previous.getPeerPrincipal();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   352
                    } catch (SSLPeerUnverifiedException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   353
                        resumingSession = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   354
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   355
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   356
90ce3da70b43 Initial load
duke
parents:
diff changeset
   357
                // validate subject identity
90ce3da70b43 Initial load
duke
parents:
diff changeset
   358
                if (resumingSession) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   359
                    CipherSuite suite = previous.getSuite();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   360
                    if (suite.keyExchange == K_KRB5 ||
90ce3da70b43 Initial load
duke
parents:
diff changeset
   361
                        suite.keyExchange == K_KRB5_EXPORT) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   362
                        Principal localPrincipal = previous.getLocalPrincipal();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   363
90ce3da70b43 Initial load
duke
parents:
diff changeset
   364
                        Subject subject = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   365
                        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   366
                            subject = AccessController.doPrivileged(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   367
                                new PrivilegedExceptionAction<Subject>() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   368
                                public Subject run() throws Exception {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   369
                                    return Krb5Util.getSubject(
2942
37d9baeb7518 6578647: Undefined requesting URL in java.net.Authenticator.getPasswordAuthentication()
weijun
parents: 2
diff changeset
   370
                                        GSSCaller.CALLER_SSL_SERVER,
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   371
                                        getAccSE());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   372
                            }});
90ce3da70b43 Initial load
duke
parents:
diff changeset
   373
                        } catch (PrivilegedActionException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   374
                            subject = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   375
                            if (debug != null && Debug.isOn("session")) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   376
                                System.out.println("Attempt to obtain" +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   377
                                                " subject failed!");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   378
                            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   379
                        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   380
90ce3da70b43 Initial load
duke
parents:
diff changeset
   381
                        if (subject != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   382
                            Set<KerberosPrincipal> principals =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   383
                                subject.getPrincipals(KerberosPrincipal.class);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   384
                            if (!principals.contains(localPrincipal)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   385
                                resumingSession = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   386
                                if (debug != null && Debug.isOn("session")) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   387
                                    System.out.println("Subject identity" +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   388
                                                        " is not the same");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   389
                                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   390
                            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   391
                                if (debug != null && Debug.isOn("session"))
90ce3da70b43 Initial load
duke
parents:
diff changeset
   392
                                    System.out.println("Subject identity" +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   393
                                                        " is same");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   394
                            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   395
                        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   396
                            resumingSession = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   397
                            if (debug != null && Debug.isOn("session"))
90ce3da70b43 Initial load
duke
parents:
diff changeset
   398
                                System.out.println("Kerberos credentials are" +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   399
                                    " not present in the current Subject;" +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   400
                                    " check if " +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   401
                                    " javax.security.auth.useSubjectAsCreds" +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   402
                                    " system property has been set to false");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   403
                        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   404
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   405
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   406
90ce3da70b43 Initial load
duke
parents:
diff changeset
   407
                if (resumingSession) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   408
                    CipherSuite suite = previous.getSuite();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   409
                    // verify that the ciphersuite from the cached session
90ce3da70b43 Initial load
duke
parents:
diff changeset
   410
                    // is in the list of client requested ciphersuites and
90ce3da70b43 Initial load
duke
parents:
diff changeset
   411
                    // we have it enabled
90ce3da70b43 Initial load
duke
parents:
diff changeset
   412
                    if ((isEnabled(suite) == false) ||
90ce3da70b43 Initial load
duke
parents:
diff changeset
   413
                            (mesg.getCipherSuites().contains(suite) == false)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   414
                        resumingSession = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   415
                    } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   416
                        // everything looks ok, set the ciphersuite
90ce3da70b43 Initial load
duke
parents:
diff changeset
   417
                        // this should be done last when we are sure we
90ce3da70b43 Initial load
duke
parents:
diff changeset
   418
                        // will resume
90ce3da70b43 Initial load
duke
parents:
diff changeset
   419
                        setCipherSuite(suite);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   420
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   421
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   422
90ce3da70b43 Initial load
duke
parents:
diff changeset
   423
                if (resumingSession) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   424
                    session = previous;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   425
                    if (debug != null &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   426
                        (Debug.isOn("handshake") || Debug.isOn("session"))) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   427
                        System.out.println("%% Resuming " + session);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   428
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   429
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   430
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   431
        } // else client did not try to resume
90ce3da70b43 Initial load
duke
parents:
diff changeset
   432
90ce3da70b43 Initial load
duke
parents:
diff changeset
   433
        //
90ce3da70b43 Initial load
duke
parents:
diff changeset
   434
        // If client hasn't specified a session we can resume, start a
90ce3da70b43 Initial load
duke
parents:
diff changeset
   435
        // new one and choose its cipher suite and compression options.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   436
        // Unless new session creation is disabled for this connection!
90ce3da70b43 Initial load
duke
parents:
diff changeset
   437
        //
90ce3da70b43 Initial load
duke
parents:
diff changeset
   438
        if (session == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   439
            if (!enableNewSession) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   440
                throw new SSLException("Client did not resume a session");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   441
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   442
            supportedCurves = (SupportedEllipticCurvesExtension)mesg.extensions.get
90ce3da70b43 Initial load
duke
parents:
diff changeset
   443
                                        (ExtensionType.EXT_ELLIPTIC_CURVES);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   444
            chooseCipherSuite(mesg);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   445
            session = new SSLSessionImpl(protocolVersion, cipherSuite,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   446
                sslContext.getSecureRandom(),
90ce3da70b43 Initial load
duke
parents:
diff changeset
   447
                getHostAddressSE(), getPortSE());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   448
            session.setLocalPrivateKey(privateKey);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   449
            // chooseCompression(mesg);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   450
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   451
90ce3da70b43 Initial load
duke
parents:
diff changeset
   452
        m1.cipherSuite = cipherSuite;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   453
        m1.sessionId = session.getSessionId();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   454
        m1.compression_method = session.getCompression();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   455
90ce3da70b43 Initial load
duke
parents:
diff changeset
   456
        if (debug != null && Debug.isOn("handshake")) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   457
            m1.print(System.out);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   458
            System.out.println("Cipher suite:  " + session.getSuite());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   459
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   460
        m1.write(output);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   461
90ce3da70b43 Initial load
duke
parents:
diff changeset
   462
        //
90ce3da70b43 Initial load
duke
parents:
diff changeset
   463
        // If we are resuming a session, we finish writing handshake
90ce3da70b43 Initial load
duke
parents:
diff changeset
   464
        // messages right now and then finish.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   465
        //
90ce3da70b43 Initial load
duke
parents:
diff changeset
   466
        if (resumingSession) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   467
            calculateConnectionKeys(session.getMasterSecret());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   468
            sendChangeCipherAndFinish(false);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   469
            return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   470
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   471
90ce3da70b43 Initial load
duke
parents:
diff changeset
   472
90ce3da70b43 Initial load
duke
parents:
diff changeset
   473
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   474
         * SECOND, write the server Certificate(s) if we need to.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   475
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   476
         * NOTE:  while an "anonymous RSA" mode is explicitly allowed by
90ce3da70b43 Initial load
duke
parents:
diff changeset
   477
         * the protocol, we can't support it since all of the SSL flavors
90ce3da70b43 Initial load
duke
parents:
diff changeset
   478
         * defined in the protocol spec are explicitly stated to require
90ce3da70b43 Initial load
duke
parents:
diff changeset
   479
         * using RSA certificates.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   480
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   481
        if (keyExchange == K_KRB5 || keyExchange == K_KRB5_EXPORT) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   482
            // Server certificates are omitted for Kerberos ciphers
90ce3da70b43 Initial load
duke
parents:
diff changeset
   483
90ce3da70b43 Initial load
duke
parents:
diff changeset
   484
        } else if ((keyExchange != K_DH_ANON) && (keyExchange != K_ECDH_ANON)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   485
            if (certs == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   486
                throw new RuntimeException("no certificates");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   487
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   488
90ce3da70b43 Initial load
duke
parents:
diff changeset
   489
            CertificateMsg m2 = new CertificateMsg(certs);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   490
90ce3da70b43 Initial load
duke
parents:
diff changeset
   491
            /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   492
             * Set local certs in the SSLSession, output
90ce3da70b43 Initial load
duke
parents:
diff changeset
   493
             * debug info, and then actually write to the client.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   494
             */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   495
            session.setLocalCertificates(certs);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   496
            if (debug != null && Debug.isOn("handshake")) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   497
                m2.print(System.out);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   498
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   499
            m2.write(output);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   500
90ce3da70b43 Initial load
duke
parents:
diff changeset
   501
            // XXX has some side effects with OS TCP buffering,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   502
            // leave it out for now
90ce3da70b43 Initial load
duke
parents:
diff changeset
   503
90ce3da70b43 Initial load
duke
parents:
diff changeset
   504
            // let client verify chain in the meantime...
90ce3da70b43 Initial load
duke
parents:
diff changeset
   505
            // output.flush();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   506
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   507
            if (certs != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   508
                throw new RuntimeException("anonymous keyexchange with certs");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   509
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   510
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   511
90ce3da70b43 Initial load
duke
parents:
diff changeset
   512
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   513
         * THIRD, the ServerKeyExchange message ... iff it's needed.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   514
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   515
         * It's usually needed unless there's an encryption-capable
90ce3da70b43 Initial load
duke
parents:
diff changeset
   516
         * RSA cert, or a D-H cert.  The notable exception is that
90ce3da70b43 Initial load
duke
parents:
diff changeset
   517
         * exportable ciphers used with big RSA keys need to downgrade
90ce3da70b43 Initial load
duke
parents:
diff changeset
   518
         * to use short RSA keys, even when the key/cert encrypts OK.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   519
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   520
90ce3da70b43 Initial load
duke
parents:
diff changeset
   521
        ServerKeyExchange m3;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   522
        switch (keyExchange) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   523
        case K_RSA:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   524
        case K_KRB5:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   525
        case K_KRB5_EXPORT:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   526
            // no server key exchange for RSA or KRB5 ciphersuites
90ce3da70b43 Initial load
duke
parents:
diff changeset
   527
            m3 = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   528
            break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   529
        case K_RSA_EXPORT:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   530
            if (JsseJce.getRSAKeyLength(certs[0].getPublicKey()) > 512) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   531
                try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   532
                    m3 = new RSA_ServerKeyExchange(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   533
                        tempPublicKey, privateKey,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   534
                        clnt_random, svr_random,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   535
                        sslContext.getSecureRandom());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   536
                    privateKey = tempPrivateKey;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   537
                } catch (GeneralSecurityException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   538
                    throwSSLException
90ce3da70b43 Initial load
duke
parents:
diff changeset
   539
                        ("Error generating RSA server key exchange", e);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   540
                    m3 = null; // make compiler happy
90ce3da70b43 Initial load
duke
parents:
diff changeset
   541
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   542
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   543
                // RSA_EXPORT with short key, don't need ServerKeyExchange
90ce3da70b43 Initial load
duke
parents:
diff changeset
   544
                m3 = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   545
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   546
            break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   547
        case K_DHE_RSA:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   548
        case K_DHE_DSS:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   549
            try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   550
                m3 = new DH_ServerKeyExchange(dh,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   551
                    privateKey,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   552
                    clnt_random.random_bytes,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   553
                    svr_random.random_bytes,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   554
                    sslContext.getSecureRandom());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   555
            } catch (GeneralSecurityException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   556
                throwSSLException("Error generating DH server key exchange", e);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   557
                m3 = null; // make compiler happy
90ce3da70b43 Initial load
duke
parents:
diff changeset
   558
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   559
            break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   560
        case K_DH_ANON:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   561
            m3 = new DH_ServerKeyExchange(dh);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   562
            break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   563
        case K_ECDHE_RSA:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   564
        case K_ECDHE_ECDSA:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   565
        case K_ECDH_ANON:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   566
            try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   567
                m3 = new ECDH_ServerKeyExchange(ecdh,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   568
                    privateKey,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   569
                    clnt_random.random_bytes,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   570
                    svr_random.random_bytes,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   571
                    sslContext.getSecureRandom());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   572
            } catch (GeneralSecurityException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   573
                throwSSLException("Error generating ECDH server key exchange", e);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   574
                m3 = null; // make compiler happy
90ce3da70b43 Initial load
duke
parents:
diff changeset
   575
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   576
            break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   577
        case K_ECDH_RSA:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   578
        case K_ECDH_ECDSA:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   579
            // ServerKeyExchange not used for fixed ECDH
90ce3da70b43 Initial load
duke
parents:
diff changeset
   580
            m3 = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   581
            break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   582
        default:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   583
            throw new RuntimeException("internal error: " + keyExchange);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   584
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   585
        if (m3 != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   586
            if (debug != null && Debug.isOn("handshake")) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   587
                m3.print(System.out);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   588
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   589
            m3.write(output);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   590
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   591
90ce3da70b43 Initial load
duke
parents:
diff changeset
   592
        //
90ce3da70b43 Initial load
duke
parents:
diff changeset
   593
        // FOURTH, the CertificateRequest message.  The details of
90ce3da70b43 Initial load
duke
parents:
diff changeset
   594
        // the message can be affected by the key exchange algorithm
90ce3da70b43 Initial load
duke
parents:
diff changeset
   595
        // in use.  For example, certs with fixed Diffie-Hellman keys
90ce3da70b43 Initial load
duke
parents:
diff changeset
   596
        // are only useful with the DH_DSS and DH_RSA key exchange
90ce3da70b43 Initial load
duke
parents:
diff changeset
   597
        // algorithms.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   598
        //
90ce3da70b43 Initial load
duke
parents:
diff changeset
   599
        // Needed only if server requires client to authenticate self.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   600
        // Illegal for anonymous flavors, so we need to check that.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   601
        //
90ce3da70b43 Initial load
duke
parents:
diff changeset
   602
        if (keyExchange == K_KRB5 || keyExchange == K_KRB5_EXPORT) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   603
            // CertificateRequest is omitted for Kerberos ciphers
90ce3da70b43 Initial load
duke
parents:
diff changeset
   604
90ce3da70b43 Initial load
duke
parents:
diff changeset
   605
        } else if (doClientAuth != SSLEngineImpl.clauth_none &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   606
                keyExchange != K_DH_ANON && keyExchange != K_ECDH_ANON) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   607
            CertificateRequest m4;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   608
            X509Certificate caCerts[];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   609
90ce3da70b43 Initial load
duke
parents:
diff changeset
   610
            caCerts = sslContext.getX509TrustManager().getAcceptedIssuers();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   611
            m4 = new CertificateRequest(caCerts, keyExchange);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   612
90ce3da70b43 Initial load
duke
parents:
diff changeset
   613
            if (debug != null && Debug.isOn("handshake")) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   614
                m4.print(System.out);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   615
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   616
            m4.write(output);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   617
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   618
90ce3da70b43 Initial load
duke
parents:
diff changeset
   619
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   620
         * FIFTH, say ServerHelloDone.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   621
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   622
        ServerHelloDone m5 = new ServerHelloDone();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   623
90ce3da70b43 Initial load
duke
parents:
diff changeset
   624
        if (debug != null && Debug.isOn("handshake")) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   625
            m5.print(System.out);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   626
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   627
        m5.write(output);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   628
90ce3da70b43 Initial load
duke
parents:
diff changeset
   629
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   630
         * Flush any buffered messages so the client will see them.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   631
         * Ideally, all the messages above go in a single network level
90ce3da70b43 Initial load
duke
parents:
diff changeset
   632
         * message to the client.  Without big Certificate chains, it's
90ce3da70b43 Initial load
duke
parents:
diff changeset
   633
         * going to be the common case.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   634
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   635
        output.flush();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   636
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   637
90ce3da70b43 Initial load
duke
parents:
diff changeset
   638
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   639
     * Choose cipher suite from among those supported by client. Sets
90ce3da70b43 Initial load
duke
parents:
diff changeset
   640
     * the cipherSuite and keyExchange variables.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   641
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   642
    private void chooseCipherSuite(ClientHello mesg) throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   643
        for (CipherSuite suite : mesg.getCipherSuites().collection()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   644
            if (isEnabled(suite) == false) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   645
                continue;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   646
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   647
            if (doClientAuth == SSLEngineImpl.clauth_required) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   648
                if ((suite.keyExchange == K_DH_ANON) || (suite.keyExchange == K_ECDH_ANON)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   649
                    continue;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   650
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   651
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   652
            if (trySetCipherSuite(suite) == false) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   653
                continue;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   654
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   655
            return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   656
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   657
        fatalSE(Alerts.alert_handshake_failure,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   658
                    "no cipher suites in common");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   659
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   660
90ce3da70b43 Initial load
duke
parents:
diff changeset
   661
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   662
     * Set the given CipherSuite, if possible. Return the result.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   663
     * The call succeeds if the CipherSuite is available and we have
90ce3da70b43 Initial load
duke
parents:
diff changeset
   664
     * the necessary certificates to complete the handshake. We don't
90ce3da70b43 Initial load
duke
parents:
diff changeset
   665
     * check if the CipherSuite is actually enabled.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   666
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   667
     * If successful, this method also generates ephemeral keys if
90ce3da70b43 Initial load
duke
parents:
diff changeset
   668
     * required for this ciphersuite. This may take some time, so this
90ce3da70b43 Initial load
duke
parents:
diff changeset
   669
     * method should only be called if you really want to use the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   670
     * CipherSuite.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   671
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   672
     * This method is called from chooseCipherSuite() in this class
90ce3da70b43 Initial load
duke
parents:
diff changeset
   673
     * and SSLServerSocketImpl.checkEnabledSuites() (as a sanity check).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   674
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   675
    boolean trySetCipherSuite(CipherSuite suite) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   676
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   677
         * If we're resuming a session we know we can
90ce3da70b43 Initial load
duke
parents:
diff changeset
   678
         * support this key exchange algorithm and in fact
90ce3da70b43 Initial load
duke
parents:
diff changeset
   679
         * have already cached the result of it in
90ce3da70b43 Initial load
duke
parents:
diff changeset
   680
         * the session state.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   681
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   682
        if (resumingSession) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   683
            return true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   684
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   685
90ce3da70b43 Initial load
duke
parents:
diff changeset
   686
        if (suite.isAvailable() == false) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   687
            return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   688
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   689
90ce3da70b43 Initial load
duke
parents:
diff changeset
   690
        KeyExchange keyExchange = suite.keyExchange;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   691
90ce3da70b43 Initial load
duke
parents:
diff changeset
   692
        // null out any existing references
90ce3da70b43 Initial load
duke
parents:
diff changeset
   693
        privateKey = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   694
        certs = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   695
        dh = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   696
        tempPrivateKey = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   697
        tempPublicKey = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   698
90ce3da70b43 Initial load
duke
parents:
diff changeset
   699
        switch (keyExchange) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   700
        case K_RSA:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   701
        case K_RSA_EXPORT:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   702
        case K_DHE_RSA:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   703
        case K_ECDHE_RSA:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   704
            // need RSA certs for authentication
90ce3da70b43 Initial load
duke
parents:
diff changeset
   705
            if (setupPrivateKeyAndChain("RSA") == false) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   706
                return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   707
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   708
90ce3da70b43 Initial load
duke
parents:
diff changeset
   709
            if (keyExchange == K_RSA_EXPORT) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   710
                try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   711
                   if (JsseJce.getRSAKeyLength(certs[0].getPublicKey()) > 512) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   712
                        if (!setupEphemeralRSAKeys(suite.exportable)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   713
                            return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   714
                        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   715
                   }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   716
                } catch (RuntimeException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   717
                    // could not determine keylength, ignore key
90ce3da70b43 Initial load
duke
parents:
diff changeset
   718
                    return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   719
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   720
            } else if (keyExchange == K_DHE_RSA) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   721
                setupEphemeralDHKeys(suite.exportable);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   722
            } else if (keyExchange == K_ECDHE_RSA) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   723
                if (setupEphemeralECDHKeys() == false) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   724
                    return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   725
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   726
            } // else nothing more to do for K_RSA
90ce3da70b43 Initial load
duke
parents:
diff changeset
   727
            break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   728
        case K_DHE_DSS:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   729
            // need DSS certs for authentication
90ce3da70b43 Initial load
duke
parents:
diff changeset
   730
            if (setupPrivateKeyAndChain("DSA") == false) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   731
                return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   732
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   733
            setupEphemeralDHKeys(suite.exportable);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   734
            break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   735
        case K_ECDHE_ECDSA:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   736
            // need EC cert signed using EC
90ce3da70b43 Initial load
duke
parents:
diff changeset
   737
            if (setupPrivateKeyAndChain("EC_EC") == false) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   738
                return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   739
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   740
            if (setupEphemeralECDHKeys() == false) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   741
                return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   742
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   743
            break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   744
        case K_ECDH_RSA:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   745
            // need EC cert signed using RSA
90ce3da70b43 Initial load
duke
parents:
diff changeset
   746
            if (setupPrivateKeyAndChain("EC_RSA") == false) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   747
                return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   748
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   749
            setupStaticECDHKeys();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   750
            break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   751
        case K_ECDH_ECDSA:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   752
            // need EC cert signed using EC
90ce3da70b43 Initial load
duke
parents:
diff changeset
   753
            if (setupPrivateKeyAndChain("EC_EC") == false) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   754
                return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   755
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   756
            setupStaticECDHKeys();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   757
            break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   758
        case K_KRB5:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   759
        case K_KRB5_EXPORT:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   760
            // need Kerberos Key
90ce3da70b43 Initial load
duke
parents:
diff changeset
   761
            if (!setupKerberosKeys()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   762
                return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   763
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   764
            break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   765
        case K_DH_ANON:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   766
            // no certs needed for anonymous
90ce3da70b43 Initial load
duke
parents:
diff changeset
   767
            setupEphemeralDHKeys(suite.exportable);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   768
            break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   769
        case K_ECDH_ANON:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   770
            // no certs needed for anonymous
90ce3da70b43 Initial load
duke
parents:
diff changeset
   771
            if (setupEphemeralECDHKeys() == false) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   772
                return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   773
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   774
            break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   775
        default:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   776
            // internal error, unknown key exchange
90ce3da70b43 Initial load
duke
parents:
diff changeset
   777
            throw new RuntimeException("Unrecognized cipherSuite: " + suite);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   778
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   779
        setCipherSuite(suite);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   780
        return true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   781
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   782
90ce3da70b43 Initial load
duke
parents:
diff changeset
   783
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   784
     * Get some "ephemeral" RSA keys for this context. This means
90ce3da70b43 Initial load
duke
parents:
diff changeset
   785
     * generating them if it's not already been done.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   786
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   787
     * Note that we currently do not implement any ciphersuites that use
90ce3da70b43 Initial load
duke
parents:
diff changeset
   788
     * strong ephemeral RSA. (We do not support the EXPORT1024 ciphersuites
90ce3da70b43 Initial load
duke
parents:
diff changeset
   789
     * and standard RSA ciphersuites prohibit ephemeral mode for some reason)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   790
     * This means that export is always true and 512 bit keys are generated.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   791
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   792
    private boolean setupEphemeralRSAKeys(boolean export) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   793
        KeyPair kp = sslContext.getEphemeralKeyManager().
90ce3da70b43 Initial load
duke
parents:
diff changeset
   794
                        getRSAKeyPair(export, sslContext.getSecureRandom());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   795
        if (kp == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   796
            return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   797
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   798
            tempPublicKey = kp.getPublic();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   799
            tempPrivateKey = kp.getPrivate();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   800
            return true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   801
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   802
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   803
90ce3da70b43 Initial load
duke
parents:
diff changeset
   804
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   805
     * Acquire some "ephemeral" Diffie-Hellman  keys for this handshake.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   806
     * We don't reuse these, for improved forward secrecy.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   807
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   808
    private void setupEphemeralDHKeys(boolean export) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   809
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   810
         * Diffie-Hellman keys ... we use 768 bit private keys due
90ce3da70b43 Initial load
duke
parents:
diff changeset
   811
         * to the "use twice as many key bits as bits you want secret"
90ce3da70b43 Initial load
duke
parents:
diff changeset
   812
         * rule of thumb, assuming we want the same size premaster
90ce3da70b43 Initial load
duke
parents:
diff changeset
   813
         * secret with Diffie-Hellman and RSA key exchanges.  Except
90ce3da70b43 Initial load
duke
parents:
diff changeset
   814
         * that exportable ciphers max out at 512 bits modulus values.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   815
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   816
        dh = new DHCrypt((export ? 512 : 768), sslContext.getSecureRandom());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   817
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   818
90ce3da70b43 Initial load
duke
parents:
diff changeset
   819
    // Setup the ephemeral ECDH parameters.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   820
    // If we cannot continue because we do not support any of the curves that
90ce3da70b43 Initial load
duke
parents:
diff changeset
   821
    // the client requested, return false. Otherwise (all is well), return true.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   822
    private boolean setupEphemeralECDHKeys() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   823
        int index = -1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   824
        if (supportedCurves != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   825
            // if the client sent the supported curves extension, pick the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   826
            // first one that we support;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   827
            for (int curveId : supportedCurves.curveIds()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   828
                if (SupportedEllipticCurvesExtension.isSupported(curveId)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   829
                    index = curveId;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   830
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   831
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   832
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   833
            if (index < 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   834
                // no match found, cannot use this ciphersuite
90ce3da70b43 Initial load
duke
parents:
diff changeset
   835
                return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   836
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   837
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   838
            // pick our preference
90ce3da70b43 Initial load
duke
parents:
diff changeset
   839
            index = SupportedEllipticCurvesExtension.DEFAULT.curveIds()[0];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   840
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   841
        String oid = SupportedEllipticCurvesExtension.getCurveOid(index);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   842
        ecdh = new ECDHCrypt(oid, sslContext.getSecureRandom());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   843
        return true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   844
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   845
90ce3da70b43 Initial load
duke
parents:
diff changeset
   846
    private void setupStaticECDHKeys() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   847
        // don't need to check whether the curve is supported, already done
90ce3da70b43 Initial load
duke
parents:
diff changeset
   848
        // in setupPrivateKeyAndChain().
90ce3da70b43 Initial load
duke
parents:
diff changeset
   849
        ecdh = new ECDHCrypt(privateKey, certs[0].getPublicKey());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   850
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   851
90ce3da70b43 Initial load
duke
parents:
diff changeset
   852
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   853
     * Retrieve the server key and certificate for the specified algorithm
90ce3da70b43 Initial load
duke
parents:
diff changeset
   854
     * from the KeyManager and set the instance variables.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   855
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   856
     * @return true if successful, false if not available or invalid
90ce3da70b43 Initial load
duke
parents:
diff changeset
   857
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   858
    private boolean setupPrivateKeyAndChain(String algorithm) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   859
        X509ExtendedKeyManager km = sslContext.getX509KeyManager();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   860
        String alias;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   861
        if (conn != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   862
            alias = km.chooseServerAlias(algorithm, null, conn);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   863
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   864
            alias = km.chooseEngineServerAlias(algorithm, null, engine);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   865
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   866
        if (alias == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   867
            return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   868
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   869
        PrivateKey tempPrivateKey = km.getPrivateKey(alias);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   870
        if (tempPrivateKey == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   871
            return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   872
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   873
        X509Certificate[] tempCerts = km.getCertificateChain(alias);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   874
        if ((tempCerts == null) || (tempCerts.length == 0)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   875
            return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   876
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   877
        String keyAlgorithm = algorithm.split("_")[0];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   878
        PublicKey publicKey = tempCerts[0].getPublicKey();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   879
        if ((tempPrivateKey.getAlgorithm().equals(keyAlgorithm) == false)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   880
                || (publicKey.getAlgorithm().equals(keyAlgorithm) == false)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   881
            return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   882
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   883
        // For ECC certs, check whether we support the EC domain parameters.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   884
        // If the client sent a SupportedEllipticCurves ClientHello extension,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   885
        // check against that too.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   886
        if (keyAlgorithm.equals("EC")) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   887
            if (publicKey instanceof ECPublicKey == false) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   888
                return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   889
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   890
            ECParameterSpec params = ((ECPublicKey)publicKey).getParams();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   891
            int index = SupportedEllipticCurvesExtension.getCurveIndex(params);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   892
            if (SupportedEllipticCurvesExtension.isSupported(index) == false) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   893
                return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   894
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   895
            if ((supportedCurves != null) && !supportedCurves.contains(index)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   896
                return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   897
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   898
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   899
        this.privateKey = tempPrivateKey;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   900
        this.certs = tempCerts;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   901
        return true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   902
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   903
90ce3da70b43 Initial load
duke
parents:
diff changeset
   904
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   905
     * Retrieve the Kerberos key for the specified server principal
90ce3da70b43 Initial load
duke
parents:
diff changeset
   906
     * from the JAAS configuration file.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   907
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   908
     * @return true if successful, false if not available or invalid
90ce3da70b43 Initial load
duke
parents:
diff changeset
   909
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   910
    private boolean setupKerberosKeys() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   911
        if (kerberosKeys != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   912
            return true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   913
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   914
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   915
            final AccessControlContext acc = getAccSE();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   916
            kerberosKeys = AccessController.doPrivileged(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   917
                new PrivilegedExceptionAction<KerberosKey[]>() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   918
                public KerberosKey[] run() throws Exception {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   919
                    // get kerberos key for the default principal
90ce3da70b43 Initial load
duke
parents:
diff changeset
   920
                    return Krb5Util.getKeys(
2942
37d9baeb7518 6578647: Undefined requesting URL in java.net.Authenticator.getPasswordAuthentication()
weijun
parents: 2
diff changeset
   921
                        GSSCaller.CALLER_SSL_SERVER, null, acc);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   922
                        }});
90ce3da70b43 Initial load
duke
parents:
diff changeset
   923
90ce3da70b43 Initial load
duke
parents:
diff changeset
   924
            // check permission to access and use the secret key of the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   925
            // Kerberized "host" service
90ce3da70b43 Initial load
duke
parents:
diff changeset
   926
            if (kerberosKeys != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   927
90ce3da70b43 Initial load
duke
parents:
diff changeset
   928
                if (debug != null && Debug.isOn("handshake")) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   929
                    System.out.println("Using Kerberos key: " +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   930
                        kerberosKeys[0]);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   931
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   932
90ce3da70b43 Initial load
duke
parents:
diff changeset
   933
                String serverPrincipal =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   934
                    kerberosKeys[0].getPrincipal().getName();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   935
                SecurityManager sm = System.getSecurityManager();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   936
                try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   937
                   if (sm != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   938
                      sm.checkPermission(new ServicePermission(serverPrincipal,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   939
                                                "accept"), acc);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   940
                   }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   941
                } catch (SecurityException se) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   942
                   kerberosKeys = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   943
                   // %%% destroy keys? or will that affect Subject?
90ce3da70b43 Initial load
duke
parents:
diff changeset
   944
                   if (debug != null && Debug.isOn("handshake"))
90ce3da70b43 Initial load
duke
parents:
diff changeset
   945
                      System.out.println("Permission to access Kerberos"
90ce3da70b43 Initial load
duke
parents:
diff changeset
   946
                                + " secret key denied");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   947
                   return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   948
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   949
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   950
            return (kerberosKeys != null);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   951
        } catch (PrivilegedActionException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   952
            // Likely exception here is LoginExceptin
90ce3da70b43 Initial load
duke
parents:
diff changeset
   953
            if (debug != null && Debug.isOn("handshake")) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   954
                System.out.println("Attempt to obtain Kerberos key failed: "
90ce3da70b43 Initial load
duke
parents:
diff changeset
   955
                                + e.toString());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   956
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   957
            return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   958
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   959
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   960
90ce3da70b43 Initial load
duke
parents:
diff changeset
   961
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   962
     * For Kerberos ciphers, the premaster secret is encrypted using
90ce3da70b43 Initial load
duke
parents:
diff changeset
   963
     * the session key. See RFC 2712.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   964
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   965
    private SecretKey clientKeyExchange(KerberosClientKeyExchange mesg)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   966
        throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   967
90ce3da70b43 Initial load
duke
parents:
diff changeset
   968
        if (debug != null && Debug.isOn("handshake")) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   969
            mesg.print(System.out);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   970
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   971
90ce3da70b43 Initial load
duke
parents:
diff changeset
   972
        // Record the principals involved in exchange
90ce3da70b43 Initial load
duke
parents:
diff changeset
   973
        session.setPeerPrincipal(mesg.getPeerPrincipal());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   974
        session.setLocalPrincipal(mesg.getLocalPrincipal());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   975
90ce3da70b43 Initial load
duke
parents:
diff changeset
   976
        byte[] b = mesg.getPreMasterSecret().getUnencrypted();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   977
        return new SecretKeySpec(b, "TlsPremasterSecret");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   978
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   979
90ce3da70b43 Initial load
duke
parents:
diff changeset
   980
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   981
     * Diffie Hellman key exchange is used when the server presented
90ce3da70b43 Initial load
duke
parents:
diff changeset
   982
     * D-H parameters in its certificate (signed using RSA or DSS/DSA),
90ce3da70b43 Initial load
duke
parents:
diff changeset
   983
     * or else the server presented no certificate but sent D-H params
90ce3da70b43 Initial load
duke
parents:
diff changeset
   984
     * in a ServerKeyExchange message.  Use of D-H is specified by the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   985
     * cipher suite chosen.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   986
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   987
     * The message optionally contains the client's D-H public key (if
90ce3da70b43 Initial load
duke
parents:
diff changeset
   988
     * it wasn't not sent in a client certificate).  As always with D-H,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   989
     * if a client and a server have each other's D-H public keys and
90ce3da70b43 Initial load
duke
parents:
diff changeset
   990
     * they use common algorithm parameters, they have a shared key
90ce3da70b43 Initial load
duke
parents:
diff changeset
   991
     * that's derived via the D-H calculation.  That key becomes the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   992
     * pre-master secret.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   993
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   994
    private SecretKey clientKeyExchange(DHClientKeyExchange mesg)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   995
            throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   996
90ce3da70b43 Initial load
duke
parents:
diff changeset
   997
        if (debug != null && Debug.isOn("handshake")) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   998
            mesg.print(System.out);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   999
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1000
        return dh.getAgreedSecret(mesg.getClientPublicKey());
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1001
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1002
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1003
    private SecretKey clientKeyExchange(ECDHClientKeyExchange mesg)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1004
            throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1005
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1006
        if (debug != null && Debug.isOn("handshake")) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1007
            mesg.print(System.out);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1008
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1009
        return ecdh.getAgreedSecret(mesg.getEncodedPoint());
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1010
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1011
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1012
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1013
     * Client wrote a message to verify the certificate it sent earlier.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1014
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1015
     * Note that this certificate isn't involved in key exchange.  Client
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1016
     * authentication messages are included in the checksums used to
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1017
     * validate the handshake (e.g. Finished messages).  Other than that,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1018
     * the _exact_ identity of the client is less fundamental to protocol
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1019
     * security than its role in selecting keys via the pre-master secret.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1020
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1021
    private void clientCertificateVerify(CertificateVerify mesg)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1022
            throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1023
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1024
        if (debug != null && Debug.isOn("handshake")) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1025
            mesg.print(System.out);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1026
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1027
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1028
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1029
            PublicKey publicKey =
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1030
                session.getPeerCertificates()[0].getPublicKey();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1031
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1032
            boolean valid = mesg.verify(protocolVersion, handshakeHash,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1033
                                        publicKey, session.getMasterSecret());
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1034
            if (valid == false) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1035
                fatalSE(Alerts.alert_bad_certificate,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1036
                            "certificate verify message signature error");
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1037
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1038
        } catch (GeneralSecurityException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1039
            fatalSE(Alerts.alert_bad_certificate,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1040
                "certificate verify format error", e);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1041
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1042
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1043
        // reset the flag for clientCertificateVerify message
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1044
        needClientVerify = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1045
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1046
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1047
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1048
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1049
     * Client writes "finished" at the end of its handshake, after cipher
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1050
     * spec is changed.   We verify it and then send ours.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1051
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1052
     * When we're resuming a session, we'll have already sent our own
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1053
     * Finished message so just the verification is needed.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1054
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1055
    private void clientFinished(Finished mesg) throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1056
        if (debug != null && Debug.isOn("handshake")) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1057
            mesg.print(System.out);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1058
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1059
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1060
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1061
         * Verify if client did send the certificate when client
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1062
         * authentication was required, otherwise server should not proceed
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1063
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1064
        if (doClientAuth == SSLEngineImpl.clauth_required) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1065
           // get X500Principal of the end-entity certificate for X509-based
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1066
           // ciphersuites, or Kerberos principal for Kerberos ciphersuites
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1067
           session.getPeerPrincipal();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1068
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1069
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1070
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1071
         * Verify if client did send clientCertificateVerify message following
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1072
         * the client Certificate, otherwise server should not proceed
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1073
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1074
        if (needClientVerify) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1075
                fatalSE(Alerts.alert_handshake_failure,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1076
                        "client did not send certificate verify message");
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1077
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1078
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1079
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1080
         * Verify the client's message with the "before" digest of messages,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1081
         * and forget about continuing to use that digest.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1082
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1083
        boolean verified = mesg.verify(protocolVersion, handshakeHash,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1084
                                Finished.CLIENT, session.getMasterSecret());
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1085
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1086
        if (!verified) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1087
            fatalSE(Alerts.alert_handshake_failure,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1088
                        "client 'finished' message doesn't verify");
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1089
            // NOTREACHED
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1090
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1091
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1092
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1093
         * OK, it verified.  If we're doing the full handshake, add that
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1094
         * "Finished" message to the hash of handshake messages, then send
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1095
         * the change_cipher_spec and Finished message.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1096
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1097
        if (!resumingSession) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1098
            input.digestNow();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1099
            sendChangeCipherAndFinish(true);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1100
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1101
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1102
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1103
         * Update the session cache only after the handshake completed, else
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1104
         * we're open to an attack against a partially completed handshake.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1105
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1106
        session.setLastAccessedTime(System.currentTimeMillis());
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1107
        if (!resumingSession && session.isRejoinable()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1108
            ((SSLSessionContextImpl)sslContext.engineGetServerSessionContext())
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1109
                .put(session);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1110
            if (debug != null && Debug.isOn("session")) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1111
                System.out.println(
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1112
                    "%% Cached server session: " + session);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1113
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1114
        } else if (!resumingSession &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1115
                debug != null && Debug.isOn("session")) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1116
            System.out.println(
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1117
                "%% Didn't cache non-resumable server session: "
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1118
                + session);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1119
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1120
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1121
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1122
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1123
     * Compute finished message with the "server" digest (and then forget
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1124
     * about that digest, it can't be used again).
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1125
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1126
    private void sendChangeCipherAndFinish(boolean finishedTag)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1127
            throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1128
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1129
        output.flush();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1130
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1131
        Finished mesg = new Finished(protocolVersion, handshakeHash,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1132
                                Finished.SERVER, session.getMasterSecret());
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1133
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1134
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1135
         * Send the change_cipher_spec record; then our Finished handshake
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1136
         * message will be the last handshake message.  Flush, and now we
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1137
         * are ready for application data!!
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1138
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1139
        sendChangeCipherSpec(mesg, finishedTag);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1140
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1141
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1142
         * Update state machine so client MUST send 'finished' next
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1143
         * The update should only take place if it is not in the fast
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1144
         * handshake mode since the server has to wait for a finished
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1145
         * message from the client.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1146
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1147
        if (finishedTag) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1148
            state = HandshakeMessage.ht_finished;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1149
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1150
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1151
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1152
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1153
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1154
     * Returns a HelloRequest message to kickstart renegotiations
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1155
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1156
    HandshakeMessage getKickstartMessage() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1157
        return new HelloRequest();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1158
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1159
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1160
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1161
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1162
     * Fault detected during handshake.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1163
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1164
    void handshakeAlert(byte description) throws SSLProtocolException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1165
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1166
        String message = Alerts.alertDescription(description);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1167
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1168
        if (debug != null && Debug.isOn("handshake")) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1169
            System.out.println("SSL -- handshake alert:  "
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1170
                + message);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1171
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1172
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1173
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1174
         * It's ok to get a no_certificate alert from a client of which
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1175
         * we *requested* authentication information.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1176
         * However, if we *required* it, then this is not acceptable.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1177
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1178
         * Anyone calling getPeerCertificates() on the
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1179
         * session will get an SSLPeerUnverifiedException.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1180
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1181
        if ((description == Alerts.alert_no_certificate) &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1182
                (doClientAuth == SSLEngineImpl.clauth_requested)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1183
            return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1184
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1185
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1186
        throw new SSLProtocolException("handshake alert: " + message);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1187
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1188
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1189
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1190
     * RSA key exchange is normally used.  The client encrypts a "pre-master
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1191
     * secret" with the server's public key, from the Certificate (or else
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1192
     * ServerKeyExchange) message that was sent to it by the server.  That's
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1193
     * decrypted using the private key before we get here.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1194
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1195
    private SecretKey clientKeyExchange(RSAClientKeyExchange mesg) throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1196
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1197
        if (debug != null && Debug.isOn("handshake")) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1198
            mesg.print(System.out);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1199
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1200
        return mesg.preMaster;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1201
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1202
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1203
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1204
     * Verify the certificate sent by the client. We'll only get one if we
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1205
     * sent a CertificateRequest to request client authentication. If we
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1206
     * are in TLS mode, the client may send a message with no certificates
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1207
     * to indicate it does not have an appropriate chain. (In SSLv3 mode,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1208
     * it would send a no certificate alert).
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1209
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1210
    private void clientCertificate(CertificateMsg mesg) throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1211
        if (debug != null && Debug.isOn("handshake")) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1212
            mesg.print(System.out);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1213
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1214
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1215
        X509Certificate[] peerCerts = mesg.getCertificateChain();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1216
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1217
        if (peerCerts.length == 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1218
            /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1219
             * If the client authentication is only *REQUESTED* (e.g.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1220
             * not *REQUIRED*, this is an acceptable condition.)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1221
             */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1222
            if (doClientAuth == SSLEngineImpl.clauth_requested) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1223
                return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1224
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1225
                fatalSE(Alerts.alert_bad_certificate,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1226
                    "null cert chain");
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1227
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1228
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1229
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1230
        // ask the trust manager to verify the chain
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1231
        X509TrustManager tm = sslContext.getX509TrustManager();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1232
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1233
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1234
            // find out the types of client authentication used
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1235
            PublicKey key = peerCerts[0].getPublicKey();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1236
            String keyAlgorithm = key.getAlgorithm();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1237
            String authType;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1238
            if (keyAlgorithm.equals("RSA")) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1239
                authType = "RSA";
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1240
            } else if (keyAlgorithm.equals("DSA")) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1241
                authType = "DSA";
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1242
            } else if (keyAlgorithm.equals("EC")) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1243
                authType = "EC";
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1244
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1245
                // unknown public key type
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1246
                authType = "UNKNOWN";
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1247
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1248
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1249
            String identificator = getHostnameVerificationSE();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1250
            if (tm instanceof X509ExtendedTrustManager) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1251
                ((X509ExtendedTrustManager)tm).checkClientTrusted(
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1252
                        (peerCerts != null ?
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1253
                            peerCerts.clone() :
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1254
                            null),
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1255
                        authType,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1256
                        getHostSE(),
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1257
                        identificator);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1258
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1259
                if (identificator != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1260
                    throw new RuntimeException(
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1261
                        "trust manager does not support peer identification");
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1262
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1263
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1264
                tm.checkClientTrusted(
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1265
                    (peerCerts != null ?
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1266
                        peerCerts.clone() :
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1267
                        peerCerts),
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1268
                    authType);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1269
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1270
        } catch (CertificateException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1271
            // This will throw an exception, so include the original error.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1272
            fatalSE(Alerts.alert_certificate_unknown, e);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1273
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1274
        // set the flag for clientCertificateVerify message
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1275
        needClientVerify = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1276
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1277
        session.setPeerCertificates(peerCerts);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1278
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1279
}