1 /*
   2  * Copyright (c) 2015, 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.IOException;
  29 import java.nio.ByteBuffer;
  30 import sun.security.ssl.SSLHandshake.HandshakeMessage;
  31 
  32 /**
  33  * Pack of the HelloRequest handshake message.
  34  */
  35 final class HelloRequest {
  36     static final SSLProducer kickstartProducer =
  37         new HelloRequestKickstartProducer();
  38 
  39     static final SSLConsumer handshakeConsumer =
  40         new HelloRequestConsumer();
  41     static final HandshakeProducer handshakeProducer =
  42         new HelloRequestProducer();
  43 
  44     /**
  45      * The HelloRequest handshake message.
  46      *
  47      * [RFC 5246] The HelloRequest message MAY be sent by the server at any
  48      * time.  HelloRequest is a simple notification that the client should
  49      * begin the negotiation process anew.
  50      *
  51      *      struct { } HelloRequest;
  52      */
  53     static final class HelloRequestMessage extends HandshakeMessage {
  54         HelloRequestMessage(HandshakeContext handshakeContext) {
  55             super(handshakeContext);
  56         }
  57 
  58         HelloRequestMessage(HandshakeContext handshakeContext,
  59                 ByteBuffer m) throws IOException {
  60             super(handshakeContext);
  61             if (m.hasRemaining()) {
  62                 handshakeContext.conContext.fatal(Alert.ILLEGAL_PARAMETER,
  63                     "Error parsing HelloRequest message: not empty");
  64             }
  65         }
  66 
  67         @Override
  68         public SSLHandshake handshakeType() {
  69             return SSLHandshake.HELLO_REQUEST;
  70         }
  71 
  72         @Override
  73         public int messageLength() {
  74             return 0;
  75         }
  76 
  77         @Override
  78         public void send(HandshakeOutStream s) throws IOException {
  79             // empty, nothing to send
  80         }
  81 
  82         @Override
  83         public String toString() {
  84             return "<empty>";
  85         }
  86     }
  87 
  88     /**
  89      * The "HelloRequest" handshake message kick start producer.
  90      */
  91     private static final
  92             class HelloRequestKickstartProducer implements SSLProducer {
  93         // Prevent instantiation of this class.
  94         private HelloRequestKickstartProducer() {
  95             // blank
  96         }
  97 
  98         @Override
  99         public byte[] produce(ConnectionContext context) throws IOException {
 100             // The producing happens in server side only.
 101             ServerHandshakeContext shc = (ServerHandshakeContext)context;
 102 
 103             HelloRequestMessage hrm = new HelloRequestMessage(shc);
 104             if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
 105                 SSLLogger.fine("Produced HelloRequest handshake message", hrm);
 106             }
 107 
 108             // Output the handshake message.
 109             hrm.write(shc.handshakeOutput);
 110             shc.handshakeOutput.flush();
 111 
 112             // update the context
 113 
 114             // What's the expected response?
 115             shc.handshakeConsumers.put(
 116                     SSLHandshake.CLIENT_HELLO.id, SSLHandshake.CLIENT_HELLO);
 117 
 118             // The handshake message has been delivered.
 119             return null;
 120         }
 121     }
 122 
 123     /**
 124      * The "HelloRequest" handshake message producer.
 125      */
 126     private static final class HelloRequestProducer
 127             implements HandshakeProducer {
 128         // Prevent instantiation of this class.
 129         private HelloRequestProducer() {
 130             // blank
 131         }
 132 
 133         @Override
 134         public byte[] produce(ConnectionContext context,
 135                 HandshakeMessage message) throws IOException {
 136             // The producing happens in server side only.
 137             ServerHandshakeContext shc = (ServerHandshakeContext)context;
 138 
 139             HelloRequestMessage hrm = new HelloRequestMessage(shc);
 140             if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
 141                 SSLLogger.fine("Produced HelloRequest handshake message", hrm);
 142             }
 143 
 144             // Output the handshake message.
 145             hrm.write(shc.handshakeOutput);
 146             shc.handshakeOutput.flush();
 147 
 148             // update the context
 149 
 150             // What's the expected response?
 151             shc.handshakeConsumers.put(
 152                     SSLHandshake.CLIENT_HELLO.id, SSLHandshake.CLIENT_HELLO);
 153 
 154             // The handshake message has been delivered.
 155             return null;
 156         }
 157     }
 158 
 159     /**
 160      * The "HelloRequest" handshake message consumer.
 161      */
 162     private static final class HelloRequestConsumer
 163             implements SSLConsumer {
 164 
 165         // Prevent instantiation of this class.
 166         private HelloRequestConsumer() {
 167             // blank
 168         }
 169 
 170         @Override
 171         public void consume(ConnectionContext context,
 172                 ByteBuffer message) throws IOException {
 173             // The consuming happens in client side only.
 174             ClientHandshakeContext chc = (ClientHandshakeContext)context;
 175 
 176             // For TLS 1.2 and prior versions, the HelloRequest message MAY
 177             // be sent by the server at any time.  Please don't clean up this
 178             // handshake consumer.
 179             HelloRequestMessage hrm = new HelloRequestMessage(chc, message);
 180             if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
 181                 SSLLogger.fine(
 182                         "Consuming HelloRequest handshake message", hrm);
 183             }
 184 
 185             if (!chc.kickstartMessageDelivered) {
 186                 if (!chc.conContext.secureRenegotiation &&
 187                         !HandshakeContext.allowUnsafeRenegotiation) {
 188                     chc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
 189                             "Unsafe renegotiation is not allowed");
 190                 }
 191 
 192                 if (!chc.conContext.secureRenegotiation) {
 193                     if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
 194                         SSLLogger.warning(
 195                                 "Continue with insecure renegotiation");
 196                     }
 197                 }
 198 
 199                 // update the responders
 200                 chc.handshakeProducers.put(
 201                         SSLHandshake.CLIENT_HELLO.id,
 202                         SSLHandshake.CLIENT_HELLO);
 203 
 204                 //
 205                 // produce response handshake message
 206                 //
 207                 SSLHandshake.CLIENT_HELLO.produce(context, hrm);
 208             } else {
 209                 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
 210                     SSLLogger.fine(
 211                             "Ingore HelloRequest, handshaking is in progress");
 212                 }
 213             }
 214         }
 215     }
 216 }
 217