History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/sun/security/ssl/EngineOutputRecord.java (1 of 18352 files). Show all

Unified · Split

java/pkg/sun/security/ssl/EngineOutputRecord.java+298−0
@@ -0,0 +1,298 @@
1+/*
2+ * Copyright (c) 2003, 2007, 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+
27+package sun.security.ssl;
28+
29+import java.io.*;
30+import java.nio.*;
31+
32+import javax.net.ssl.SSLException;
33+import sun.misc.HexDumpEncoder;
34+
35+
36+/**
37+ * A OutputRecord class extension which uses external ByteBuffers
38+ * or the internal ByteArrayOutputStream for data manipulations.
39+ * <P>
40+ * Instead of rewriting this entire class
41+ * to use ByteBuffers, we leave things intact, so handshake, CCS,
42+ * and alerts will continue to use the internal buffers, but application
43+ * data will use external buffers.
44+ *
45+ * @author Brad Wetmore
46+ */
47+final class EngineOutputRecord extends OutputRecord {
48+
49+ private EngineWriter writer;
50+
51+ private boolean finishedMsg = false;
52+
53+ /*
54+ * All handshake hashing is done by the superclass
55+ */
56+
57+ /*
58+ * Default constructor makes a record supporting the maximum
59+ * SSL record size. It allocates the header bytes directly.
60+ *
61+ * @param type the content type for the record
62+ */
63+ EngineOutputRecord(byte type, SSLEngineImpl engine) {
64+ super(type, recordSize(type));
65+ writer = engine.writer;
66+ }
67+
68+ /**
69+ * Get the size of the buffer we need for records of the specified
70+ * type.
71+ * <P>
72+ * Application data buffers will provide their own byte buffers,
73+ * and will not use the internal byte caching.
74+ */
75+ private static int recordSize(byte type) {
76+ switch (type) {
77+
78+ case ct_change_cipher_spec:
79+ case ct_alert:
80+ return maxAlertRecordSize;
81+
82+ case ct_handshake:
83+ return maxRecordSize;
84+
85+ case ct_application_data:
86+ return 0;
87+ }
88+
89+ throw new RuntimeException("Unknown record type: " + type);
90+ }
91+
92+ void setFinishedMsg() {
93+ finishedMsg = true;
94+ }
95+
96+ public void flush() throws IOException {
97+ finishedMsg = false;
98+ }
99+
100+ boolean isFinishedMsg() {
101+ return finishedMsg;
102+ }
103+
104+
105+ /**
106+ * Calculate the MAC value, storing the result either in
107+ * the internal buffer, or at the end of the destination
108+ * ByteBuffer.
109+ * <P>
110+ * We assume that the higher levels have assured us enough
111+ * room, otherwise we'll indirectly throw a
112+ * BufferOverFlowException runtime exception.
113+ *
114+ * position should equal limit, and points to the next
115+ * free spot.
116+ */
117+ private void addMAC(MAC signer, ByteBuffer bb)
118+ throws IOException {
119+
120+ if (signer.MAClen() != 0) {
121+ byte[] hash = signer.compute(contentType(), bb);
122+
123+ /*
124+ * position was advanced to limit in compute above.
125+ *
126+ * Mark next area as writable (above layers should have
127+ * established that we have plenty of room), then write
128+ * out the hash.
129+ */
130+ bb.limit(bb.limit() + hash.length);
131+ bb.put(hash);
132+ }
133+ }
134+
135+ /*
136+ * Encrypt a ByteBuffer.
137+ *
138+ * We assume that the higher levels have assured us enough
139+ * room for the encryption (plus padding), otherwise we'll
140+ * indirectly throw a BufferOverFlowException runtime exception.
141+ *
142+ * position and limit will be the same, and points to the
143+ * next free spot.
144+ */
145+ void encrypt(CipherBox box, ByteBuffer bb) {
146+ box.encrypt(bb);
147+ }
148+
149+ /*
150+ * Override the actual write below. We do things this way to be
151+ * consistent with InputRecord. InputRecord may try to write out
152+ * data to the peer, and *then* throw an Exception. This forces
153+ * data to be generated/output before the exception is ever
154+ * generated.
155+ */
156+ void writeBuffer(OutputStream s, byte [] buf, int off, int len)
157+ throws IOException {
158+ /*
159+ * Copy data out of buffer, it's ready to go.
160+ */
161+ ByteBuffer netBB = (ByteBuffer)
162+ ByteBuffer.allocate(len).put(buf, 0, len).flip();
163+ writer.putOutboundData(netBB);
164+ }
165+
166+ /*
167+ * Main method for writing non-application data.
168+ * We MAC/encrypt, then send down for processing.
169+ */
170+ void write(MAC writeMAC, CipherBox writeCipher) throws IOException {
171+ /*
172+ * Sanity check.
173+ */
174+ switch (contentType()) {
175+ case ct_change_cipher_spec:
176+ case ct_alert:
177+ case ct_handshake:
178+ break;
179+ default:
180+ throw new RuntimeException("unexpected byte buffers");
181+ }
182+
183+ /*
184+ * Don't bother to really write empty records. We went this
185+ * far to drive the handshake machinery, for correctness; not
186+ * writing empty records improves performance by cutting CPU
187+ * time and network resource usage. Also, some protocol
188+ * implementations are fragile and don't like to see empty
189+ * records, so this increases robustness.
190+ *
191+ * (Even change cipher spec messages have a byte of data!)
192+ */
193+ if (!isEmpty()) {
194+ // compress(); // eventually
195+ addMAC(writeMAC);
196+ encrypt(writeCipher);
197+ write((OutputStream)null); // send down for processing
198+ }
199+ return;
200+ }
201+
202+ /**
203+ * Main wrap/write driver.
204+ */
205+ void write(EngineArgs ea, MAC writeMAC, CipherBox writeCipher)
206+ throws IOException {
207+ /*
208+ * sanity check to make sure someone didn't inadvertantly
209+ * send us an impossible combination we don't know how
210+ * to process.
211+ */
212+ assert(contentType() == ct_application_data);
213+
214+ /*
215+ * Have we set the MAC's yet? If not, we're not ready
216+ * to process application data yet.
217+ */
218+ if (writeMAC == MAC.NULL) {
219+ return;
220+ }
221+
222+ /*
223+ * Don't bother to really write empty records. We went this
224+ * far to drive the handshake machinery, for correctness; not
225+ * writing empty records improves performance by cutting CPU
226+ * time and network resource usage. Also, some protocol
227+ * implementations are fragile and don't like to see empty
228+ * records, so this increases robustness.
229+ */
230+ int length = Math.min(ea.getAppRemaining(), maxDataSize);
231+ if (length == 0) {
232+ return;
233+ }
234+
235+ /*
236+ * Copy out existing buffer values.
237+ */
238+ ByteBuffer dstBB = ea.netData;
239+ int dstPos = dstBB.position();
240+ int dstLim = dstBB.limit();
241+
242+ /*
243+ * Where to put the data. Jump over the header.
244+ *
245+ * Don't need to worry about SSLv2 rewrites, if we're here,
246+ * that's long since done.
247+ */
248+ int dstData = dstPos + headerSize;
249+ dstBB.position(dstData);
250+
251+ ea.gather(length);
252+
253+ /*
254+ * "flip" but skip over header again, add MAC & encrypt
255+ * addMAC will expand the limit to reflect the new
256+ * data.
257+ */
258+ dstBB.limit(dstBB.position());
259+ dstBB.position(dstData);
260+ addMAC(writeMAC, dstBB);
261+
262+ /*
263+ * Encrypt may pad, so again the limit may have changed.
264+ */
265+ dstBB.limit(dstBB.position());
266+ dstBB.position(dstData);
267+ encrypt(writeCipher, dstBB);
268+
269+ if (debug != null
270+ && (Debug.isOn("record") || Debug.isOn("handshake"))) {
271+ if ((debug != null && Debug.isOn("record"))
272+ || contentType() == ct_change_cipher_spec)
273+ System.out.println(Thread.currentThread().getName()
274+ // v3.0/v3.1 ...
275+ + ", WRITE: " + protocolVersion
276+ + " " + InputRecord.contentName(contentType())
277+ + ", length = " + length);
278+ }
279+
280+ int packetLength = dstBB.limit() - dstData;
281+
282+ /*
283+ * Finish out the record header.
284+ */
285+ dstBB.put(dstPos, contentType());
286+ dstBB.put(dstPos + 1, protocolVersion.major);
287+ dstBB.put(dstPos + 2, protocolVersion.minor);
288+ dstBB.put(dstPos + 3, (byte)(packetLength >> 8));
289+ dstBB.put(dstPos + 4, (byte)packetLength);
290+
291+ /*
292+ * Position was already set by encrypt() above.
293+ */
294+ dstBB.limit(dstLim);
295+
296+ return;
297+ }
298+}