< prev index next >
src/java.base/share/classes/sun/security/ssl/Alert.java
Print this page
*** 1,7 ****
/*
! * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
--- 1,7 ----
/*
! * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
*** 23,223 ****
* questions.
*/
package sun.security.ssl;
import javax.net.ssl.*;
! /*
! * A simple class to congregate alerts, their definitions, and common
! * support methods.
*/
! final class Alerts {
! /*
! * Alerts are always a fixed two byte format (level/description).
*/
! // warnings and fatal errors are package private facilities/constants
! // Alert levels (enum AlertLevel)
! static final byte alert_warning = 1;
! static final byte alert_fatal = 2;
! /*
! * Alert descriptions (enum AlertDescription)
! *
! * We may not use them all in our processing, but if someone
! * sends us one, we can at least convert it to a string for the
! * user.
*/
! static final byte alert_close_notify = 0;
! static final byte alert_unexpected_message = 10;
! static final byte alert_bad_record_mac = 20;
! static final byte alert_decryption_failed = 21;
! static final byte alert_record_overflow = 22;
! static final byte alert_decompression_failure = 30;
! static final byte alert_handshake_failure = 40;
! static final byte alert_no_certificate = 41;
! static final byte alert_bad_certificate = 42;
! static final byte alert_unsupported_certificate = 43;
! static final byte alert_certificate_revoked = 44;
! static final byte alert_certificate_expired = 45;
! static final byte alert_certificate_unknown = 46;
! static final byte alert_illegal_parameter = 47;
! static final byte alert_unknown_ca = 48;
! static final byte alert_access_denied = 49;
! static final byte alert_decode_error = 50;
! static final byte alert_decrypt_error = 51;
! static final byte alert_export_restriction = 60;
! static final byte alert_protocol_version = 70;
! static final byte alert_insufficient_security = 71;
! static final byte alert_internal_error = 80;
! static final byte alert_user_canceled = 90;
! static final byte alert_no_renegotiation = 100;
!
! // from RFC 3546 (TLS Extensions)
! static final byte alert_unsupported_extension = 110;
! static final byte alert_certificate_unobtainable = 111;
! static final byte alert_unrecognized_name = 112;
! static final byte alert_bad_certificate_status_response = 113;
! static final byte alert_bad_certificate_hash_value = 114;
!
! // from RFC 7301 (TLS ALPN Extension)
! static final byte alert_no_application_protocol = 120;
!
! static String alertDescription(byte code) {
! switch (code) {
!
! case alert_close_notify:
! return "close_notify";
! case alert_unexpected_message:
! return "unexpected_message";
! case alert_bad_record_mac:
! return "bad_record_mac";
! case alert_decryption_failed:
! return "decryption_failed";
! case alert_record_overflow:
! return "record_overflow";
! case alert_decompression_failure:
! return "decompression_failure";
! case alert_handshake_failure:
! return "handshake_failure";
! case alert_no_certificate:
! return "no_certificate";
! case alert_bad_certificate:
! return "bad_certificate";
! case alert_unsupported_certificate:
! return "unsupported_certificate";
! case alert_certificate_revoked:
! return "certificate_revoked";
! case alert_certificate_expired:
! return "certificate_expired";
! case alert_certificate_unknown:
! return "certificate_unknown";
! case alert_illegal_parameter:
! return "illegal_parameter";
! case alert_unknown_ca:
! return "unknown_ca";
! case alert_access_denied:
! return "access_denied";
! case alert_decode_error:
! return "decode_error";
! case alert_decrypt_error:
! return "decrypt_error";
! case alert_export_restriction:
! return "export_restriction";
! case alert_protocol_version:
! return "protocol_version";
! case alert_insufficient_security:
! return "insufficient_security";
! case alert_internal_error:
! return "internal_error";
! case alert_user_canceled:
! return "user_canceled";
! case alert_no_renegotiation:
! return "no_renegotiation";
! case alert_unsupported_extension:
! return "unsupported_extension";
! case alert_certificate_unobtainable:
! return "certificate_unobtainable";
! case alert_unrecognized_name:
! return "unrecognized_name";
! case alert_bad_certificate_status_response:
! return "bad_certificate_status_response";
! case alert_bad_certificate_hash_value:
! return "bad_certificate_hash_value";
! case alert_no_application_protocol:
! return "no_application_protocol";
!
! default:
! return "<UNKNOWN ALERT: " + (code & 0x0ff) + ">";
! }
! }
!
! static SSLException getSSLException(byte description, String reason) {
! return getSSLException(description, null, reason);
! }
!
! /*
! * Try to be a little more specific in our choice of
! * exceptions to throw.
*/
! static SSLException getSSLException(byte description, Throwable cause,
! String reason) {
! SSLException e;
! // the SSLException classes do not have a no-args constructor
! // make up a message if there is none
! if (reason == null) {
! if (cause != null) {
! reason = cause.toString();
! } else {
! reason = "";
}
}
! switch (description) {
! case alert_handshake_failure:
! case alert_no_certificate:
! case alert_bad_certificate:
! case alert_unsupported_certificate:
! case alert_certificate_revoked:
! case alert_certificate_expired:
! case alert_certificate_unknown:
! case alert_unknown_ca:
! case alert_access_denied:
! case alert_decrypt_error:
! case alert_export_restriction:
! case alert_insufficient_security:
! case alert_unsupported_extension:
! case alert_certificate_unobtainable:
! case alert_unrecognized_name:
! case alert_bad_certificate_status_response:
! case alert_bad_certificate_hash_value:
! case alert_no_application_protocol:
! e = new SSLHandshakeException(reason);
! break;
!
! case alert_close_notify:
! case alert_unexpected_message:
! case alert_bad_record_mac:
! case alert_decryption_failed:
! case alert_record_overflow:
! case alert_decompression_failure:
! case alert_illegal_parameter:
! case alert_decode_error:
! case alert_protocol_version:
! case alert_internal_error:
! case alert_user_canceled:
! case alert_no_renegotiation:
! default:
! e = new SSLException(reason);
! break;
}
! if (cause != null) {
! e.initCause(cause);
}
- return e;
}
}
--- 23,269 ----
* questions.
*/
package sun.security.ssl;
+ import java.io.IOException;
+ import java.nio.ByteBuffer;
+ import java.text.MessageFormat;
+ import java.util.Locale;
import javax.net.ssl.*;
! /**
! * SSL/(D)TLS Alter description
*/
+ enum Alert {
+ // Please refer to TLS Alert Registry for the latest (D)TLS Alert values:
+ // https://www.iana.org/assignments/tls-parameters/
+ CLOSE_NOTIFY ((byte)0, "close_notify", false),
+ UNEXPECTED_MESSAGE ((byte)10, "unexpected_message", false),
+ BAD_RECORD_MAC ((byte)20, "bad_record_mac", false),
+ DECRYPTION_FAILED ((byte)21, "decryption_failed", false),
+ RECORD_OVERFLOW ((byte)22, "record_overflow", false),
+ DECOMPRESSION_FAILURE ((byte)30, "decompression_failure", false),
+ HANDSHAKE_FAILURE ((byte)40, "handshake_failure", true),
+ NO_CERTIFICATE ((byte)41, "no_certificate", true),
+ BAD_CERTIFICATE ((byte)42, "bad_certificate", true),
+ UNSUPPORTED_CERTIFCATE ((byte)43, "unsupported_certificate", true),
+ CERTIFICATE_REVOKED ((byte)44, "certificate_revoked", true),
+ CERTIFICATE_EXPIRED ((byte)45, "certificate_expired", true),
+ CERTIFICATE_UNKNOWN ((byte)46, "certificate_unknown", true),
+ ILLEGAL_PARAMETER ((byte)47, "illegal_parameter", true),
+ UNKNOWN_CA ((byte)48, "unknown_ca", true),
+ ACCESS_DENIED ((byte)49, "access_denied", true),
+ DECODE_ERROR ((byte)50, "decode_error", true),
+ DECRYPT_ERROR ((byte)51, "decrypt_error", true),
+ EXPORT_RESTRICTION ((byte)60, "export_restriction", true),
+ PROTOCOL_VERSION ((byte)70, "protocol_version", true),
+ INSUFFICIENT_SECURITY ((byte)71, "insufficient_security", true),
+ INTERNAL_ERROR ((byte)80, "internal_error", false),
+ INAPPROPRIATE_FALLBACK ((byte)86, "inappropriate_fallback", false),
+ USER_CANCELED ((byte)90, "user_canceled", false),
+ NO_RENEGOTIATION ((byte)100, "no_renegotiation", true),
+ MISSING_EXTENSION ((byte)109, "missing_extension", true),
+ UNSUPPORTED_EXTENSION ((byte)110, "unsupported_extension", true),
+ CERT_UNOBTAINABLE ((byte)111, "certificate_unobtainable", true),
+ UNRECOGNIZED_NAME ((byte)112, "unrecognized_name", true),
+ BAD_CERT_STATUS_RESPONSE((byte)113,
+ "bad_certificate_status_response", true),
+ BAD_CERT_HASH_VALUE ((byte)114, "bad_certificate_hash_value", true),
+ UNKNOWN_PSK_IDENTITY ((byte)115, "unknown_psk_identity", true),
+ CERTIFICATE_REQUIRED ((byte)116, "certificate_required", true),
+ NO_APPLICATION_PROTOCOL ((byte)120, "no_application_protocol", true);
+
+ // ordinal value of the Alert
+ final byte id;
+
+ // description of the Alert
+ final String description;
+
+ // Does tha alert happen during handshake only?
+ final boolean handshakeOnly;
+
+ // Alert message consumer
+ static final SSLConsumer alertConsumer = new AlertConsumer();
+
+ private Alert(byte id, String description, boolean handshakeOnly) {
+ this.id = id;
+ this.description = description;
+ this.handshakeOnly = handshakeOnly;
+ }
+
+ static Alert valueOf(byte id) {
+ for (Alert al : Alert.values()) {
+ if (al.id == id) {
+ return al;
+ }
+ }
+
+ return null;
+ }
! static String nameOf(byte id) {
! for (Alert al : Alert.values()) {
! if (al.id == id) {
! return al.description;
! }
! }
!
! return "UNKNOWN ALERT (" + (id & 0x0FF) + ")";
! }
!
! SSLException createSSLException(String reason) {
! return createSSLException(reason, null);
! }
! SSLException createSSLException(String reason, Throwable cause) {
! if (reason == null) {
! reason = (cause != null) ? cause.getMessage() : "";
! }
!
! SSLException ssle = handshakeOnly ?
! new SSLHandshakeException(reason) : new SSLException(reason);
! if (cause != null) {
! ssle.initCause(cause);
! }
!
! return ssle;
! }
!
! /**
! * SSL/(D)TLS Alert level.
*/
+ enum Level {
+ WARNING ((byte)1, "warning"),
+ FATAL ((byte)2, "fatal");
+
+ // ordinal value of the Alert level
+ final byte level;
+
+ // description of the Alert level
+ final String description;
+
+ private Level(byte level, String description) {
+ this.level = level;
+ this.description = description;
+ }
! static Level valueOf(byte level) {
! for (Level lv : Level.values()) {
! if (lv.level == level) {
! return lv;
! }
! }
! return null;
! }
! static String nameOf(byte level) {
! for (Level lv : Level.values()) {
! if (lv.level == level) {
! return lv.description;
! }
! }
!
! return "UNKNOWN ALERT LEVEL (" + (level & 0x0FF) + ")";
! }
! }
!
! /**
! * The Alert message.
*/
! private static final class AlertMessage {
! private final byte level; // level
! private final byte id; // description
!
! AlertMessage(TransportContext context,
! ByteBuffer m) throws IOException {
! // struct {
! // AlertLevel level;
! // AlertDescription description;
! // } Alert;
! if (m.remaining() != 2) {
! context.fatal(Alert.ILLEGAL_PARAMETER,
! "Invalid Alert message: no sufficient data");
! }
!
! this.level = m.get(); // level
! this.id = m.get(); // description
! }
!
! @Override
! public String toString() {
! MessageFormat messageFormat = new MessageFormat(
! "\"Alert\": '{'\n" +
! " \"level\" : \"{0}\",\n" +
! " \"description\": \"{1}\"\n" +
! "'}'",
! Locale.ENGLISH);
!
! Object[] messageFields = {
! Level.nameOf(level),
! Alert.nameOf(id)
! };
!
! return messageFormat.format(messageFields);
! }
! }
!
! /**
! * Consumer of alert messages
*/
! private static final class AlertConsumer implements SSLConsumer {
! // Prevent instantiation of this class.
! private AlertConsumer() {
! // blank
! }
! @Override
! public void consume(ConnectionContext context,
! ByteBuffer m) throws IOException {
! TransportContext tc = (TransportContext)context;
!
! AlertMessage am = new AlertMessage(tc, m);
! if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
! SSLLogger.fine("Received alert message", am);
}
+
+ Level level = Level.valueOf(am.level);
+ Alert alert = Alert.valueOf(am.id);
+ if (alert == Alert.CLOSE_NOTIFY) {
+ if (tc.handshakeContext != null) {
+ tc.fatal(Alert.UNEXPECTED_MESSAGE,
+ "Received close_notify during handshake");
}
!
! tc.isInputCloseNotified = true;
! tc.closeInbound();
! } else if ((level == Level.WARNING) && (alert != null)) {
! // Terminate the connection if an alert with a level of warning
! // is received during handshaking, except the no_certificate
! // warning.
! if (alert.handshakeOnly && (tc.handshakeContext != null)) {
! // It's OK to get a no_certificate alert from a client of
! // which we requested client authentication. However,
! // if we required it, then this is not acceptable.
! if (tc.sslConfig.isClientMode ||
! alert != Alert.NO_CERTIFICATE ||
! (tc.sslConfig.clientAuthType !=
! ClientAuthType.CLIENT_AUTH_REQUESTED)) {
! tc.fatal(Alert.HANDSHAKE_FAILURE,
! "received handshake warning: " + alert.description);
! } // Otherwise, ignore the warning
! } // Otherwise, ignore the warning.
! } else { // fatal or unknown
! String diagnostic;
! if (alert == null) {
! alert = Alert.UNEXPECTED_MESSAGE;
! diagnostic = "Unknown alert description (" + am.id + ")";
! } else {
! diagnostic = "Received fatal alert: " + alert.description;
}
! tc.fatal(alert, diagnostic, true, null);
! }
}
}
}
< prev index next >