1 /* 2 * Copyright (c) 2006, 2017, 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.io.PrintStream; 30 import java.util.*; 31 import javax.net.ssl.*; 32 33 /** 34 * This file contains all the classes relevant to TLS Extensions for the 35 * ClientHello and ServerHello messages. The extension mechanism and 36 * several extensions are defined in RFC 6066. Additional extensions are 37 * defined in the ECC RFC 4492 and the ALPN extension is defined in RFC 7301. 38 * 39 * Currently, only the two ECC extensions are fully supported. 40 * 41 * The classes contained in this file are: 42 * . HelloExtensions: a List of extensions as used in the client hello 43 * and server hello messages. 44 * . ExtensionType: an enum style class for the extension type 45 * . HelloExtension: abstract base class for all extensions. All subclasses 46 * must be immutable. 47 * 48 * . UnknownExtension: used to represent all parsed extensions that we do not 49 * explicitly support. 50 * . ServerNameExtension: the server_name extension. 51 * . SignatureAlgorithmsExtension: the signature_algorithms extension. 52 * . SupportedGroupsExtension: the supported groups extension. 53 * . EllipticPointFormatsExtension: the ECC supported point formats 54 * (compressed/uncompressed) extension. 55 * . ALPNExtension: the application_layer_protocol_negotiation extension. 56 * 57 * @since 1.6 58 * @author Andreas Sterbenz 59 */ 60 final class HelloExtensions { 61 62 private List<HelloExtension> extensions; 63 private int encodedLength; 64 65 HelloExtensions() { 66 extensions = Collections.emptyList(); 67 } 68 69 HelloExtensions(HandshakeInStream s) throws IOException { 70 int len = s.getInt16(); 71 extensions = new ArrayList<HelloExtension>(); 72 encodedLength = len + 2; 73 while (len > 0) { 74 int type = s.getInt16(); 75 int extlen = s.getInt16(); 76 ExtensionType extType = ExtensionType.get(type); 77 HelloExtension extension; 78 if (extType == ExtensionType.EXT_SERVER_NAME) { 79 extension = new ServerNameExtension(s, extlen); 80 } else if (extType == ExtensionType.EXT_SIGNATURE_ALGORITHMS) { 81 extension = new SignatureAlgorithmsExtension(s, extlen); 82 } else if (extType == ExtensionType.EXT_SUPPORTED_GROUPS) { 83 extension = new SupportedGroupsExtension(s, extlen); 84 } else if (extType == ExtensionType.EXT_EC_POINT_FORMATS) { 85 extension = new EllipticPointFormatsExtension(s, extlen); 86 } else if (extType == ExtensionType.EXT_RENEGOTIATION_INFO) { 87 extension = new RenegotiationInfoExtension(s, extlen); 88 } else if (extType == ExtensionType.EXT_ALPN) { 89 extension = new ALPNExtension(s, extlen); 90 } else if (extType == ExtensionType.EXT_MAX_FRAGMENT_LENGTH) { 91 extension = new MaxFragmentLengthExtension(s, extlen); 92 } else if (extType == ExtensionType.EXT_STATUS_REQUEST) { 93 extension = new CertStatusReqExtension(s, extlen); 94 } else if (extType == ExtensionType.EXT_STATUS_REQUEST_V2) { 95 extension = new CertStatusReqListV2Extension(s, extlen); 96 } else { 97 extension = new UnknownExtension(s, extlen, extType); 98 } 99 extensions.add(extension); 100 len -= extlen + 4; 101 } 102 if (len != 0) { 103 throw new SSLProtocolException( 104 "Error parsing extensions: extra data"); 105 } 106 } 107 108 // Return the List of extensions. Must not be modified by the caller. 109 List<HelloExtension> list() { 110 return extensions; 111 } 112 113 void add(HelloExtension ext) { 114 if (extensions.isEmpty()) { 115 extensions = new ArrayList<HelloExtension>(); 116 } 117 extensions.add(ext); 118 encodedLength = -1; 119 } 120 121 HelloExtension get(ExtensionType type) { 122 for (HelloExtension ext : extensions) { 123 if (ext.type == type) { 124 return ext; 125 } 126 } 127 return null; 128 } 129 130 int length() { 131 if (encodedLength >= 0) { 132 return encodedLength; 133 } 134 if (extensions.isEmpty()) { 135 encodedLength = 0; 136 } else { 137 encodedLength = 2; 138 for (HelloExtension ext : extensions) { 139 encodedLength += ext.length(); 140 } 141 } 142 return encodedLength; 143 } 144 145 void send(HandshakeOutStream s) throws IOException { 146 int length = length(); 147 if (length == 0) { 148 return; 149 } 150 s.putInt16(length - 2); 151 for (HelloExtension ext : extensions) { 152 ext.send(s); 153 } 154 } 155 156 void print(PrintStream s) throws IOException { 157 for (HelloExtension ext : extensions) { 158 s.println(ext.toString()); 159 } 160 } 161 }