jdk/src/java.base/share/classes/sun/security/ssl/SSLSocketInputRecord.java
author xuelei
Tue, 02 Jun 2015 04:01:04 +0000
changeset 30904 ec0224270f90
child 34687 d302ed125dc9
permissions -rw-r--r--
8043758: Datagram Transport Layer Security (DTLS) Reviewed-by: jnimeh, weijun, mullan, wetmore
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
30904
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
     1
/*
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
     2
 * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
     4
 *
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
     7
 * published by the Free Software Foundation.  Oracle designates this
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
     9
 * by Oracle in the LICENSE file that accompanied this code.
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    10
 *
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    15
 * accompanied this code).
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    16
 *
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    20
 *
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    22
 * or visit www.oracle.com if you need additional information or have any
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    23
 * questions.
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    24
 */
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    25
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    26
package sun.security.ssl;
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    27
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    28
import java.io.*;
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    29
import java.nio.*;
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    30
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    31
import javax.crypto.BadPaddingException;
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    32
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    33
import javax.net.ssl.*;
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    34
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    35
import sun.misc.HexDumpEncoder;
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    36
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    37
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    38
/**
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    39
 * {@code InputRecord} implementation for {@code SSLSocket}.
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    40
 *
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    41
 * @author David Brownell
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    42
 */
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    43
final class SSLSocketInputRecord extends InputRecord implements SSLRecord {
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    44
    private OutputStream deliverStream = null;
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    45
    private byte[] temporary = new byte[1024];
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    46
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    47
    // used by handshake hash computation for handshake fragment
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    48
    private byte prevType = -1;
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    49
    private int hsMsgOff = 0;
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    50
    private int hsMsgLen = 0;
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    51
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    52
    private boolean formatVerified = false;     // SSLv2 ruled out?
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    53
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    54
    private boolean hasHeader = false;          // Had read the record header
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    55
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    56
    SSLSocketInputRecord() {
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    57
        this.readAuthenticator = MAC.TLS_NULL;
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    58
    }
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    59
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    60
    @Override
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    61
    int bytesInCompletePacket(InputStream is) throws IOException {
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    62
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    63
        if (!hasHeader) {
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    64
            // read exactly one record
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    65
            int really = read(is, temporary, 0, headerSize);
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    66
            if (really < 0) {
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    67
                throw new EOFException("SSL peer shut down incorrectly");
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    68
            }
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    69
            hasHeader = true;
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    70
        }
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    71
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    72
        byte byteZero = temporary[0];
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    73
        int len = 0;
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    74
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    75
        /*
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    76
         * If we have already verified previous packets, we can
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    77
         * ignore the verifications steps, and jump right to the
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    78
         * determination.  Otherwise, try one last hueristic to
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    79
         * see if it's SSL/TLS.
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    80
         */
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    81
        if (formatVerified ||
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    82
                (byteZero == ct_handshake) || (byteZero == ct_alert)) {
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    83
            /*
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    84
             * Last sanity check that it's not a wild record
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    85
             */
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    86
            ProtocolVersion recordVersion =
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    87
                    ProtocolVersion.valueOf(temporary[1], temporary[2]);
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    88
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    89
            // check the record version
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    90
            checkRecordVersion(recordVersion, false);
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    91
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    92
            /*
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    93
             * Reasonably sure this is a V3, disable further checks.
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    94
             * We can't do the same in the v2 check below, because
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    95
             * read still needs to parse/handle the v2 clientHello.
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    96
             */
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    97
            formatVerified = true;
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    98
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
    99
            /*
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   100
             * One of the SSLv3/TLS message types.
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   101
             */
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   102
            len = ((temporary[3] & 0xFF) << 8) +
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   103
                   (temporary[4] & 0xFF) + headerSize;
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   104
        } else {
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   105
            /*
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   106
             * Must be SSLv2 or something unknown.
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   107
             * Check if it's short (2 bytes) or
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   108
             * long (3) header.
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   109
             *
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   110
             * Internals can warn about unsupported SSLv2
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   111
             */
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   112
            boolean isShort = ((byteZero & 0x80) != 0);
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   113
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   114
            if (isShort && ((temporary[2] == 1) || (temporary[2] == 4))) {
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   115
                ProtocolVersion recordVersion =
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   116
                        ProtocolVersion.valueOf(temporary[3], temporary[4]);
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   117
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   118
                // check the record version
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   119
                checkRecordVersion(recordVersion, true);
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   120
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   121
                /*
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   122
                 * Client or Server Hello
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   123
                 */
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   124
                //
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   125
                // Short header is using here.  We reverse the code here
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   126
                // in case it it used in the future.
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   127
                //
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   128
                // int mask = (isShort ? 0x7F : 0x3F);
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   129
                // len = ((byteZero & mask) << 8) +
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   130
                //        (temporary[1] & 0xFF) + (isShort ? 2 : 3);
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   131
                //
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   132
                len = ((byteZero & 0x7F) << 8) + (temporary[1] & 0xFF) + 2;
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   133
            } else {
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   134
                // Gobblygook!
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   135
                throw new SSLException(
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   136
                        "Unrecognized SSL message, plaintext connection?");
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   137
            }
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   138
        }
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   139
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   140
        return len;
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   141
    }
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   142
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   143
    // destination.position() is zero.
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   144
    @Override
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   145
    Plaintext decode(InputStream is, ByteBuffer destination)
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   146
            throws IOException, BadPaddingException {
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   147
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   148
        if (isClosed) {
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   149
            return null;
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   150
        }
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   151
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   152
        if (!hasHeader) {
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   153
            // read exactly one record
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   154
            int really = read(is, temporary, 0, headerSize);
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   155
            if (really < 0) {
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   156
                throw new EOFException("SSL peer shut down incorrectly");
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   157
            }
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   158
            hasHeader = true;
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   159
        }
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   160
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   161
        Plaintext plaintext = null;
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   162
        if (!formatVerified) {
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   163
            formatVerified = true;
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   164
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   165
            /*
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   166
             * The first record must either be a handshake record or an
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   167
             * alert message. If it's not, it is either invalid or an
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   168
             * SSLv2 message.
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   169
             */
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   170
            if ((temporary[0] != ct_handshake) &&
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   171
                (temporary[0] != ct_alert)) {
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   172
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   173
                plaintext = handleUnknownRecord(is, temporary, destination);
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   174
            }
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   175
        }
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   176
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   177
        if (plaintext == null) {
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   178
            plaintext = decodeInputRecord(is, temporary, destination);
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   179
        }
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   180
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   181
        // The record header should has comsumed.
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   182
        hasHeader = false;
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   183
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   184
        return plaintext;
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   185
    }
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   186
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   187
    @Override
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   188
    void setDeliverStream(OutputStream outputStream) {
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   189
        this.deliverStream = outputStream;
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   190
    }
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   191
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   192
    // Note that destination may be null
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   193
    private Plaintext decodeInputRecord(InputStream is, byte[] header,
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   194
            ByteBuffer destination) throws IOException, BadPaddingException {
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   195
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   196
        byte contentType = header[0];
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   197
        byte majorVersion = header[1];
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   198
        byte minorVersion = header[2];
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   199
        int contentLen = ((header[3] & 0xFF) << 8) + (header[4] & 0xFF);
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   200
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   201
        //
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   202
        // Check for upper bound.
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   203
        //
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   204
        // Note: May check packetSize limit in the future.
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   205
        if (contentLen < 0 || contentLen > maxLargeRecordSize - headerSize) {
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   206
            throw new SSLProtocolException(
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   207
                "Bad input record size, TLSCiphertext.length = " + contentLen);
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   208
        }
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   209
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   210
        //
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   211
        // Read a complete record.
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   212
        //
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   213
        if (destination == null) {
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   214
            destination = ByteBuffer.allocate(headerSize + contentLen);
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   215
        }  // Otherwise, the destination buffer should have enough room.
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   216
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   217
        int dstPos = destination.position();
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   218
        destination.put(temporary, 0, headerSize);
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   219
        while (contentLen > 0) {
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   220
            int howmuch = Math.min(temporary.length, contentLen);
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   221
            int really = read(is, temporary, 0, howmuch);
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   222
            if (really < 0) {
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   223
                throw new EOFException("SSL peer shut down incorrectly");
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   224
            }
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   225
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   226
            destination.put(temporary, 0, howmuch);
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   227
            contentLen -= howmuch;
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   228
        }
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   229
        destination.flip();
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   230
        destination.position(dstPos + headerSize);
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   231
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   232
        if (debug != null && Debug.isOn("record")) {
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   233
             System.out.println(Thread.currentThread().getName() +
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   234
                    ", READ: " +
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   235
                    ProtocolVersion.valueOf(majorVersion, minorVersion) +
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   236
                    " " + Record.contentName(contentType) + ", length = " +
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   237
                    destination.remaining());
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   238
        }
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   239
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   240
        //
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   241
        // Decrypt the fragment
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   242
        //
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   243
        ByteBuffer plaintext =
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   244
            decrypt(readAuthenticator, readCipher, contentType, destination);
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   245
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   246
        if ((contentType != ct_handshake) && (hsMsgOff != hsMsgLen)) {
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   247
            throw new SSLProtocolException(
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   248
                    "Expected to get a handshake fragment");
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   249
        }
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   250
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   251
        //
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   252
        // handshake hashing
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   253
        //
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   254
        if (contentType == ct_handshake) {
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   255
            int pltPos = plaintext.position();
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   256
            int pltLim = plaintext.limit();
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   257
            int frgPos = pltPos;
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   258
            for (int remains = plaintext.remaining(); remains > 0;) {
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   259
                int howmuch;
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   260
                byte handshakeType;
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   261
                if (hsMsgOff < hsMsgLen) {
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   262
                    // a fragment of the handshake message
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   263
                    howmuch = Math.min((hsMsgLen - hsMsgOff), remains);
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   264
                    handshakeType = prevType;
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   265
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   266
                    hsMsgOff += howmuch;
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   267
                    if (hsMsgOff == hsMsgLen) {
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   268
                        // Now is a complete handshake message.
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   269
                        hsMsgOff = 0;
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   270
                        hsMsgLen = 0;
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   271
                    }
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   272
                } else {    // hsMsgOff == hsMsgLen, a new handshake message
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   273
                    handshakeType = plaintext.get();
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   274
                    int handshakeLen = ((plaintext.get() & 0xFF) << 16) |
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   275
                                       ((plaintext.get() & 0xFF) << 8) |
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   276
                                        (plaintext.get() & 0xFF);
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   277
                    plaintext.position(frgPos);
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   278
                    if (remains < (handshakeLen + 1)) { // 1: handshake type
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   279
                        // This handshake message is fragmented.
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   280
                        prevType = handshakeType;
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   281
                        hsMsgOff = remains - 4;         // 4: handshake header
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   282
                        hsMsgLen = handshakeLen;
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   283
                    }
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   284
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   285
                    howmuch = Math.min(handshakeLen + 4, remains);
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   286
                }
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   287
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   288
                plaintext.limit(frgPos + howmuch);
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   289
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   290
                if (handshakeType == HandshakeMessage.ht_hello_request) {
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   291
                    // omitted from handshake hash computation
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   292
                } else if ((handshakeType != HandshakeMessage.ht_finished) &&
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   293
                    (handshakeType != HandshakeMessage.ht_certificate_verify)) {
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   294
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   295
                    if (handshakeHash == null) {
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   296
                        // used for cache only
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   297
                        handshakeHash = new HandshakeHash(false);
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   298
                    }
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   299
                    handshakeHash.update(plaintext);
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   300
                } else {
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   301
                    // Reserve until this handshake message has been processed.
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   302
                    if (handshakeHash == null) {
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   303
                        // used for cache only
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   304
                        handshakeHash = new HandshakeHash(false);
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   305
                    }
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   306
                    handshakeHash.reserve(plaintext);
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   307
                }
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   308
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   309
                plaintext.position(frgPos + howmuch);
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   310
                plaintext.limit(pltLim);
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   311
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   312
                frgPos += howmuch;
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   313
                remains -= howmuch;
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   314
            }
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   315
            plaintext.position(pltPos);
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   316
        }
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   317
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   318
        return new Plaintext(contentType,
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   319
                majorVersion, minorVersion, -1, -1L, plaintext);
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   320
                // recordEpoch, recordSeq, plaintext);
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   321
    }
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   322
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   323
    private Plaintext handleUnknownRecord(InputStream is, byte[] header,
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   324
            ByteBuffer destination) throws IOException, BadPaddingException {
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   325
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   326
        byte firstByte = header[0];
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   327
        byte thirdByte = header[2];
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   328
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   329
        // Does it look like a Version 2 client hello (V2ClientHello)?
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   330
        if (((firstByte & 0x80) != 0) && (thirdByte == 1)) {
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   331
            /*
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   332
             * If SSLv2Hello is not enabled, throw an exception.
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   333
             */
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   334
            if (helloVersion != ProtocolVersion.SSL20Hello) {
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   335
                throw new SSLHandshakeException("SSLv2Hello is not enabled");
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   336
            }
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   337
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   338
            byte majorVersion = header[3];
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   339
            byte minorVersion = header[4];
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   340
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   341
            if ((majorVersion == ProtocolVersion.SSL20Hello.major) &&
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   342
                (minorVersion == ProtocolVersion.SSL20Hello.minor)) {
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   343
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   344
                /*
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   345
                 * Looks like a V2 client hello, but not one saying
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   346
                 * "let's talk SSLv3".  So we need to send an SSLv2
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   347
                 * error message, one that's treated as fatal by
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   348
                 * clients (Otherwise we'll hang.)
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   349
                 */
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   350
                deliverStream.write(SSLRecord.v2NoCipher);      // SSLv2Hello
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   351
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   352
                if (debug != null) {
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   353
                    if (Debug.isOn("record")) {
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   354
                         System.out.println(Thread.currentThread().getName() +
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   355
                                "Requested to negotiate unsupported SSLv2!");
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   356
                    }
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   357
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   358
                    if (Debug.isOn("packet")) {
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   359
                        Debug.printHex(
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   360
                                "[Raw write]: length = " +
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   361
                                SSLRecord.v2NoCipher.length,
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   362
                                SSLRecord.v2NoCipher);
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   363
                    }
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   364
                }
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   365
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   366
                throw new SSLException("Unsupported SSL v2.0 ClientHello");
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   367
            }
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   368
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   369
            int msgLen = ((header[0] & 0x7F) << 8) | (header[1] & 0xFF);
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   370
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   371
            if (destination == null) {
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   372
                destination = ByteBuffer.allocate(headerSize + msgLen);
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   373
            }
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   374
            destination.put(temporary, 0, headerSize);
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   375
            msgLen -= 3;            // had read 3 bytes of content as header
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   376
            while (msgLen > 0) {
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   377
                int howmuch = Math.min(temporary.length, msgLen);
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   378
                int really = read(is, temporary, 0, howmuch);
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   379
                if (really < 0) {
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   380
                    throw new EOFException("SSL peer shut down incorrectly");
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   381
                }
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   382
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   383
                destination.put(temporary, 0, howmuch);
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   384
                msgLen -= howmuch;
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   385
            }
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   386
            destination.flip();
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   387
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   388
            /*
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   389
             * If we can map this into a V3 ClientHello, read and
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   390
             * hash the rest of the V2 handshake, turn it into a
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   391
             * V3 ClientHello message, and pass it up.
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   392
             */
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   393
            destination.position(2);     // exclude the header
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   394
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   395
            if (handshakeHash == null) {
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   396
                // used for cache only
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   397
                handshakeHash = new HandshakeHash(false);
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   398
            }
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   399
            handshakeHash.update(destination);
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   400
            destination.position(0);
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   401
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   402
            ByteBuffer converted = convertToClientHello(destination);
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   403
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   404
            if (debug != null && Debug.isOn("packet")) {
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   405
                 Debug.printHex(
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   406
                        "[Converted] ClientHello", converted);
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   407
            }
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   408
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   409
            return new Plaintext(ct_handshake,
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   410
                majorVersion, minorVersion, -1, -1L, converted);
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   411
        } else {
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   412
            if (((firstByte & 0x80) != 0) && (thirdByte == 4)) {
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   413
                throw new SSLException("SSL V2.0 servers are not supported.");
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   414
            }
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   415
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   416
            throw new SSLException("Unsupported or unrecognized SSL message");
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   417
        }
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   418
    }
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   419
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   420
    // Read the exact bytes of data, otherwise, return -1.
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   421
    private static int read(InputStream is,
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   422
            byte[] buffer, int offset, int len) throws IOException {
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   423
        int n = 0;
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   424
        while (n < len) {
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   425
            int readLen = is.read(buffer, offset + n, len - n);
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   426
            if (readLen < 0) {
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   427
                return -1;
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   428
            }
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   429
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   430
            if (debug != null && Debug.isOn("packet")) {
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   431
                 Debug.printHex(
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   432
                        "[Raw read]: length = " + readLen,
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   433
                        buffer, offset + n, readLen);
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   434
            }
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   435
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   436
            n += readLen;
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   437
        }
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   438
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   439
        return n;
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   440
    }
ec0224270f90 8043758: Datagram Transport Layer Security (DTLS)
xuelei
parents:
diff changeset
   441
}