Path: blob/master/src/java.base/share/classes/sun/security/ssl/Alert.java
41159 views
/*1* Copyright (c) 2003, 2019, 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 javax.net.ssl.SSLException;32import javax.net.ssl.SSLHandshakeException;33import javax.net.ssl.SSLProtocolException;3435/**36* SSL/(D)TLS Alter description37*/38enum Alert {39// Please refer to TLS Alert Registry for the latest (D)TLS Alert values:40// https://www.iana.org/assignments/tls-parameters/41CLOSE_NOTIFY ((byte)0, "close_notify", false),42UNEXPECTED_MESSAGE ((byte)10, "unexpected_message", false),43BAD_RECORD_MAC ((byte)20, "bad_record_mac", false),44DECRYPTION_FAILED ((byte)21, "decryption_failed", false),45RECORD_OVERFLOW ((byte)22, "record_overflow", false),46DECOMPRESSION_FAILURE ((byte)30, "decompression_failure", false),47HANDSHAKE_FAILURE ((byte)40, "handshake_failure", true),48NO_CERTIFICATE ((byte)41, "no_certificate", true),49BAD_CERTIFICATE ((byte)42, "bad_certificate", true),50UNSUPPORTED_CERTIFICATE ((byte)43, "unsupported_certificate", true),51CERTIFICATE_REVOKED ((byte)44, "certificate_revoked", true),52CERTIFICATE_EXPIRED ((byte)45, "certificate_expired", true),53CERTIFICATE_UNKNOWN ((byte)46, "certificate_unknown", true),54ILLEGAL_PARAMETER ((byte)47, "illegal_parameter", true),55UNKNOWN_CA ((byte)48, "unknown_ca", true),56ACCESS_DENIED ((byte)49, "access_denied", true),57DECODE_ERROR ((byte)50, "decode_error", true),58DECRYPT_ERROR ((byte)51, "decrypt_error", true),59EXPORT_RESTRICTION ((byte)60, "export_restriction", true),60PROTOCOL_VERSION ((byte)70, "protocol_version", true),61INSUFFICIENT_SECURITY ((byte)71, "insufficient_security", true),62INTERNAL_ERROR ((byte)80, "internal_error", false),63INAPPROPRIATE_FALLBACK ((byte)86, "inappropriate_fallback", false),64USER_CANCELED ((byte)90, "user_canceled", false),65NO_RENEGOTIATION ((byte)100, "no_renegotiation", true),66MISSING_EXTENSION ((byte)109, "missing_extension", true),67UNSUPPORTED_EXTENSION ((byte)110, "unsupported_extension", true),68CERT_UNOBTAINABLE ((byte)111, "certificate_unobtainable", true),69UNRECOGNIZED_NAME ((byte)112, "unrecognized_name", true),70BAD_CERT_STATUS_RESPONSE((byte)113,71"bad_certificate_status_response", true),72BAD_CERT_HASH_VALUE ((byte)114, "bad_certificate_hash_value", true),73UNKNOWN_PSK_IDENTITY ((byte)115, "unknown_psk_identity", true),74CERTIFICATE_REQUIRED ((byte)116, "certificate_required", true),75NO_APPLICATION_PROTOCOL ((byte)120, "no_application_protocol", true);7677// ordinal value of the Alert78final byte id;7980// description of the Alert81final String description;8283// Does tha alert happen during handshake only?84final boolean handshakeOnly;8586// Alert message consumer87static final SSLConsumer alertConsumer = new AlertConsumer();8889private Alert(byte id, String description, boolean handshakeOnly) {90this.id = id;91this.description = description;92this.handshakeOnly = handshakeOnly;93}9495static Alert valueOf(byte id) {96for (Alert al : Alert.values()) {97if (al.id == id) {98return al;99}100}101102return null;103}104105static String nameOf(byte id) {106for (Alert al : Alert.values()) {107if (al.id == id) {108return al.description;109}110}111112return "UNKNOWN ALERT (" + (id & 0x0FF) + ")";113}114115SSLException createSSLException(String reason) {116return createSSLException(reason, null);117}118119SSLException createSSLException(String reason, Throwable cause) {120if (reason == null) {121reason = (cause != null) ? cause.getMessage() : "";122}123124SSLException ssle;125if (cause instanceof IOException) {126ssle = new SSLException(reason);127} else if ((this == UNEXPECTED_MESSAGE)) {128ssle = new SSLProtocolException(reason);129} else if (handshakeOnly) {130ssle = new SSLHandshakeException(reason);131} else {132ssle = new SSLException(reason);133}134135if (cause != null) {136ssle.initCause(cause);137}138139return ssle;140}141142/**143* SSL/(D)TLS Alert level.144*/145enum Level {146WARNING ((byte)1, "warning"),147FATAL ((byte)2, "fatal");148149// ordinal value of the Alert level150final byte level;151152// description of the Alert level153final String description;154155private Level(byte level, String description) {156this.level = level;157this.description = description;158}159160static Level valueOf(byte level) {161for (Level lv : Level.values()) {162if (lv.level == level) {163return lv;164}165}166167return null;168}169170static String nameOf(byte level) {171for (Level lv : Level.values()) {172if (lv.level == level) {173return lv.description;174}175}176177return "UNKNOWN ALERT LEVEL (" + (level & 0x0FF) + ")";178}179}180181/**182* The Alert message.183*/184private static final class AlertMessage {185private final byte level; // level186private final byte id; // description187188AlertMessage(TransportContext context,189ByteBuffer m) throws IOException {190// struct {191// AlertLevel level;192// AlertDescription description;193// } Alert;194if (m.remaining() != 2) {195throw context.fatal(Alert.ILLEGAL_PARAMETER,196"Invalid Alert message: no sufficient data");197}198199this.level = m.get(); // level200this.id = m.get(); // description201}202203@Override204public String toString() {205MessageFormat messageFormat = new MessageFormat(206"\"Alert\": '{'\n" +207" \"level\" : \"{0}\",\n" +208" \"description\": \"{1}\"\n" +209"'}'",210Locale.ENGLISH);211212Object[] messageFields = {213Level.nameOf(level),214Alert.nameOf(id)215};216217return messageFormat.format(messageFields);218}219}220221/**222* Consumer of alert messages223*/224private static final class AlertConsumer implements SSLConsumer {225// Prevent instantiation of this class.226private AlertConsumer() {227// blank228}229230@Override231public void consume(ConnectionContext context,232ByteBuffer m) throws IOException {233TransportContext tc = (TransportContext)context;234235AlertMessage am = new AlertMessage(tc, m);236if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {237SSLLogger.fine("Received alert message", am);238}239240Level level = Level.valueOf(am.level);241Alert alert = Alert.valueOf(am.id);242if (alert == Alert.CLOSE_NOTIFY) {243tc.isInputCloseNotified = true;244tc.closeInbound();245246if (tc.peerUserCanceled) {247tc.closeOutbound();248} else if (tc.handshakeContext != null) {249throw tc.fatal(Alert.UNEXPECTED_MESSAGE,250"Received close_notify during handshake");251}252} else if (alert == Alert.USER_CANCELED) {253if (level == Level.WARNING) {254tc.peerUserCanceled = true;255} else {256throw tc.fatal(alert,257"Received fatal close_notify alert", true, null);258}259} else if ((level == Level.WARNING) && (alert != null)) {260// Terminate the connection if an alert with a level of warning261// is received during handshaking, except the no_certificate262// warning.263if (alert.handshakeOnly && (tc.handshakeContext != null)) {264// It's OK to get a no_certificate alert from a client of265// which we requested client authentication. However,266// if we required it, then this is not acceptable.267if (tc.sslConfig.isClientMode ||268alert != Alert.NO_CERTIFICATE ||269(tc.sslConfig.clientAuthType !=270ClientAuthType.CLIENT_AUTH_REQUESTED)) {271throw tc.fatal(Alert.HANDSHAKE_FAILURE,272"received handshake warning: " + alert.description);273} else {274// Otherwise ignore the warning but remove the275// Certificate and CertificateVerify handshake276// consumer so the state machine doesn't expect it.277tc.handshakeContext.handshakeConsumers.remove(278SSLHandshake.CERTIFICATE.id);279tc.handshakeContext.handshakeConsumers.remove(280SSLHandshake.CERTIFICATE_VERIFY.id);281}282} // Otherwise, ignore the warning283} else { // fatal or unknown284String diagnostic;285if (alert == null) {286alert = Alert.UNEXPECTED_MESSAGE;287diagnostic = "Unknown alert description (" + am.id + ")";288} else {289diagnostic = "Received fatal alert: " + alert.description;290}291292throw tc.fatal(alert, diagnostic, true, null);293}294}295}296}297298299