Path: blob/master/src/java.base/share/classes/sun/security/ssl/HelloVerifyRequest.java
41159 views
/*1* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.security.ssl;2627import java.io.IOException;28import java.nio.ByteBuffer;29import java.text.MessageFormat;30import java.util.Locale;31import sun.security.ssl.ClientHello.ClientHelloMessage;32import sun.security.ssl.SSLHandshake.HandshakeMessage;3334/**35* Pack of the HelloVerifyRequest handshake message.36*/37final class HelloVerifyRequest {38static final SSLConsumer handshakeConsumer =39new HelloVerifyRequestConsumer();40static final HandshakeProducer handshakeProducer =41new HelloVerifyRequestProducer();4243/**44* The HelloVerifyRequest handshake message [RFC 6347].45*/46static final class HelloVerifyRequestMessage extends HandshakeMessage {47final int serverVersion;48final byte[] cookie;4950HelloVerifyRequestMessage(HandshakeContext context,51HandshakeMessage message) throws IOException {52super(context);53// This happens in server side only.54ServerHandshakeContext shc =55(ServerHandshakeContext)context;56ClientHelloMessage clientHello = (ClientHelloMessage)message;5758HelloCookieManager hcMgr =59shc.sslContext.getHelloCookieManager(ProtocolVersion.DTLS10);60this.serverVersion = shc.clientHelloVersion;61this.cookie = hcMgr.createCookie(shc, clientHello);62}6364HelloVerifyRequestMessage(HandshakeContext context,65ByteBuffer m) throws IOException {66super(context);67// This happens in client side only.68ClientHandshakeContext chc = (ClientHandshakeContext)context;6970// struct {71// ProtocolVersion server_version;72// opaque cookie<0..2^8-1>;73// } HelloVerifyRequest;74if (m.remaining() < 3) {75throw chc.conContext.fatal(Alert.ILLEGAL_PARAMETER,76"Invalid HelloVerifyRequest: no sufficient data");77}7879byte major = m.get();80byte minor = m.get();81this.serverVersion = ((major & 0xFF) << 8) | (minor & 0xFF);82this.cookie = Record.getBytes8(m);83}8485@Override86public SSLHandshake handshakeType() {87return SSLHandshake.HELLO_VERIFY_REQUEST;88}8990@Override91public int messageLength() {92return 3 + cookie.length; // 2: the length of protocol version93// +1: the cookie length94}9596@Override97public void send(HandshakeOutStream hos) throws IOException {98hos.putInt8((byte)((serverVersion >>> 8) & 0xFF));99hos.putInt8((byte)(serverVersion & 0xFF));100hos.putBytes8(cookie);101}102103@Override104public String toString() {105MessageFormat messageFormat = new MessageFormat(106"\"HelloVerifyRequest\": '{'\n" +107" \"server version\" : \"{0}\",\n" +108" \"cookie\" : \"{1}\",\n" +109"'}'",110Locale.ENGLISH);111Object[] messageFields = {112ProtocolVersion.nameOf(serverVersion),113Utilities.toHexString(cookie),114};115116return messageFormat.format(messageFields);117}118}119120/**121* The "HelloVerifyRequest" handshake message producer.122*/123private static final124class HelloVerifyRequestProducer implements HandshakeProducer {125// Prevent instantiation of this class.126private HelloVerifyRequestProducer() {127// blank128}129130@Override131public byte[] produce(ConnectionContext context,132HandshakeMessage message) throws IOException {133// The producing happens in server side only.134ServerHandshakeContext shc = (ServerHandshakeContext)context;135136// clean up this producer137shc.handshakeProducers.remove(SSLHandshake.HELLO_VERIFY_REQUEST.id);138139HelloVerifyRequestMessage hvrm =140new HelloVerifyRequestMessage(shc, message);141if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {142SSLLogger.fine(143"Produced HelloVerifyRequest handshake message", hvrm);144}145146// Output the handshake message.147hvrm.write(shc.handshakeOutput);148shc.handshakeOutput.flush();149150// update the context151152// Stateless, clean up the handshake context as well?153shc.handshakeHash.finish(); // forgot about the handshake hash154shc.handshakeExtensions.clear();155156// What's the expected response?157shc.handshakeConsumers.put(158SSLHandshake.CLIENT_HELLO.id, SSLHandshake.CLIENT_HELLO);159160// The handshake message has been delivered.161return null;162}163}164165/**166* The "HelloVerifyRequest" handshake message consumer.167*/168private static final class HelloVerifyRequestConsumer169implements SSLConsumer {170171// Prevent instantiation of this class.172private HelloVerifyRequestConsumer() {173// blank174}175176@Override177public void consume(ConnectionContext context,178ByteBuffer message) throws IOException {179// The consuming happens in client side only.180ClientHandshakeContext chc = (ClientHandshakeContext)context;181182// clean up this consumer183chc.handshakeConsumers.remove(SSLHandshake.HELLO_VERIFY_REQUEST.id);184if (!chc.handshakeConsumers.isEmpty()) {185chc.handshakeConsumers.remove(SSLHandshake.SERVER_HELLO.id);186}187if (!chc.handshakeConsumers.isEmpty()) {188throw chc.conContext.fatal(Alert.UNEXPECTED_MESSAGE,189"No more message expected before " +190"HelloVerifyRequest is processed");191}192193// Refresh handshake hash.194chc.handshakeHash.finish(); // forgot about the handshake hash195196HelloVerifyRequestMessage hvrm =197new HelloVerifyRequestMessage(chc, message);198if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {199SSLLogger.fine(200"Consuming HelloVerifyRequest handshake message", hvrm);201}202203// Note that HelloVerifyRequest.server_version is used solely to204// indicate packet formatting, and not as part of version205// negotiation. Need not to check version values match for206// HelloVerifyRequest message.207chc.initialClientHelloMsg.setHelloCookie(hvrm.cookie);208209//210// produce response handshake message211//212SSLHandshake.CLIENT_HELLO.produce(context, hvrm);213}214}215}216217218219