1 /* 2 * Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package sun.security.ssl; 27 28 import java.io.ByteArrayOutputStream; 29 import java.io.IOException; 30 import java.nio.ByteBuffer; 31 32 /** 33 * Output stream for handshake data. This is used only internally 34 * to the SSL classes. 35 * 36 * MT note: one thread at a time is presumed be writing handshake 37 * messages, but (after initial connection setup) it's possible to 38 * have other threads reading/writing application data. It's the 39 * SSLSocketImpl class that synchronizes record writes. 40 * 41 * @author David Brownell 42 */ 43 public class HandshakeOutStream extends ByteArrayOutputStream { 44 45 OutputRecord outputRecord; // May be null if not actually used to 46 // output handshake message records. 47 HandshakeOutStream(OutputRecord outputRecord)48 HandshakeOutStream(OutputRecord outputRecord) { 49 super(); 50 this.outputRecord = outputRecord; 51 } 52 53 // Complete a handshaking message write. Called by HandshakeMessage. complete()54 void complete() throws IOException { 55 if (size() < 4) { // 4: handshake message header size 56 // internal_error alert will be triggered 57 throw new RuntimeException("handshake message is not available"); 58 } 59 60 if (outputRecord != null) { 61 if (!outputRecord.isClosed()) { 62 outputRecord.encodeHandshake(buf, 0, count); 63 } else { 64 if (SSLLogger.isOn && SSLLogger.isOn("ssl")) { 65 SSLLogger.warning("outbound has closed, ignore outbound " + 66 "handshake messages", ByteBuffer.wrap(buf, 0, count)); 67 } 68 } 69 70 // reset the byte array output stream 71 reset(); 72 } // otherwise, the handshake outstream is temporarily used only. 73 } 74 75 // 76 // overridden ByteArrayOutputStream methods 77 // 78 79 @Override write(byte[] b, int off, int len)80 public void write(byte[] b, int off, int len) { 81 // The maximum fragment size is 24 bytes. 82 checkOverflow(len, Record.OVERFLOW_OF_INT24); 83 super.write(b, off, len); 84 } 85 86 @Override flush()87 public void flush() throws IOException { 88 if (outputRecord != null) { 89 outputRecord.flush(); 90 } 91 } 92 93 // 94 // handshake output stream management functions 95 // 96 97 /* 98 * Put integers encoded in standard 8, 16, 24, and 32 bit 99 * big endian formats. Note that OutputStream.write(int) only 100 * writes the least significant 8 bits and ignores the rest. 101 */ putInt8(int i)102 void putInt8(int i) throws IOException { 103 checkOverflow(i, Record.OVERFLOW_OF_INT08); 104 super.write(i); 105 } 106 putInt16(int i)107 void putInt16(int i) throws IOException { 108 checkOverflow(i, Record.OVERFLOW_OF_INT16); 109 super.write(i >> 8); 110 super.write(i); 111 } 112 putInt24(int i)113 void putInt24(int i) throws IOException { 114 checkOverflow(i, Record.OVERFLOW_OF_INT24); 115 super.write(i >> 16); 116 super.write(i >> 8); 117 super.write(i); 118 } 119 putInt32(int i)120 void putInt32(int i) throws IOException { 121 super.write(i >> 24); 122 super.write(i >> 16); 123 super.write(i >> 8); 124 super.write(i); 125 } 126 127 /* 128 * Put byte arrays with length encoded as 8, 16, 24 bit 129 * integers in big-endian format. 130 */ putBytes8(byte[] b)131 void putBytes8(byte[] b) throws IOException { 132 if (b == null) { 133 putInt8(0); 134 } else { 135 putInt8(b.length); 136 super.write(b, 0, b.length); 137 } 138 } 139 putBytes16(byte[] b)140 public void putBytes16(byte[] b) throws IOException { 141 if (b == null) { 142 putInt16(0); 143 } else { 144 putInt16(b.length); 145 super.write(b, 0, b.length); 146 } 147 } 148 putBytes24(byte[] b)149 void putBytes24(byte[] b) throws IOException { 150 if (b == null) { 151 putInt24(0); 152 } else { 153 putInt24(b.length); 154 super.write(b, 0, b.length); 155 } 156 } 157 158 /* 159 * Does the specified length overflow the limitation? 160 */ checkOverflow(int length, int limit)161 private static void checkOverflow(int length, int limit) { 162 if (length >= limit) { 163 // internal_error alert will be triggered 164 throw new RuntimeException( 165 "Field length overflow, the field length (" + 166 length + ") should be less than " + limit); 167 } 168 } 169 } 170