8236039: JSSE Client does not accept status_request extension in CertificateRequest messages for TLS 1.3

Reviewed-by: xuelei
This commit is contained in:
Jamil Nimeh 2020-06-21 18:44:20 -07:00
parent e23aaedacf
commit 7a3bf58b8a
3 changed files with 55 additions and 43 deletions

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -39,11 +39,7 @@ import java.util.Locale;
import javax.net.ssl.SSLProtocolException; import javax.net.ssl.SSLProtocolException;
import sun.security.provider.certpath.OCSPResponse; import sun.security.provider.certpath.OCSPResponse;
import sun.security.provider.certpath.ResponderId; import sun.security.provider.certpath.ResponderId;
import static sun.security.ssl.SSLExtension.CH_STATUS_REQUEST;
import static sun.security.ssl.SSLExtension.CH_STATUS_REQUEST_V2;
import sun.security.ssl.SSLExtension.ExtensionConsumer; import sun.security.ssl.SSLExtension.ExtensionConsumer;
import static sun.security.ssl.SSLExtension.SH_STATUS_REQUEST;
import static sun.security.ssl.SSLExtension.SH_STATUS_REQUEST_V2;
import sun.security.ssl.SSLExtension.SSLExtensionSpec; import sun.security.ssl.SSLExtension.SSLExtensionSpec;
import sun.security.ssl.SSLHandshake.HandshakeMessage; import sun.security.ssl.SSLHandshake.HandshakeMessage;
import sun.security.util.DerInputStream; import sun.security.util.DerInputStream;
@ -434,8 +430,9 @@ final class CertStatusExtension {
} else { } else {
extBuilder.append(",\n"); extBuilder.append(",\n");
} }
extBuilder.append( extBuilder.append("{\n").
"{\n" + Utilities.indent(ext.toString()) + "}"); append(Utilities.indent(ext.toString())).
append("}");
} }
extsStr = extBuilder.toString(); extsStr = extBuilder.toString();
@ -552,11 +549,11 @@ final class CertStatusExtension {
return null; return null;
} }
if (!chc.sslConfig.isAvailable(CH_STATUS_REQUEST)) { if (!chc.sslConfig.isAvailable(SSLExtension.CH_STATUS_REQUEST)) {
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
SSLLogger.fine( SSLLogger.fine(
"Ignore unavailable extension: " + "Ignore unavailable extension: " +
CH_STATUS_REQUEST.name); SSLExtension.CH_STATUS_REQUEST.name);
} }
return null; return null;
} }
@ -568,8 +565,8 @@ final class CertStatusExtension {
byte[] extData = new byte[] {0x01, 0x00, 0x00, 0x00, 0x00}; byte[] extData = new byte[] {0x01, 0x00, 0x00, 0x00, 0x00};
// Update the context. // Update the context.
chc.handshakeExtensions.put( chc.handshakeExtensions.put(SSLExtension.CH_STATUS_REQUEST,
CH_STATUS_REQUEST, CertStatusRequestSpec.DEFAULT); CertStatusRequestSpec.DEFAULT);
return extData; return extData;
} }
@ -593,10 +590,10 @@ final class CertStatusExtension {
// The consuming happens in server side only. // The consuming happens in server side only.
ServerHandshakeContext shc = (ServerHandshakeContext)context; ServerHandshakeContext shc = (ServerHandshakeContext)context;
if (!shc.sslConfig.isAvailable(CH_STATUS_REQUEST)) { if (!shc.sslConfig.isAvailable(SSLExtension.CH_STATUS_REQUEST)) {
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
SSLLogger.fine("Ignore unavailable extension: " + SSLLogger.fine("Ignore unavailable extension: " +
CH_STATUS_REQUEST.name); SSLExtension.CH_STATUS_REQUEST.name);
} }
return; // ignore the extension return; // ignore the extension
} }
@ -610,7 +607,7 @@ final class CertStatusExtension {
} }
// Update the context. // Update the context.
shc.handshakeExtensions.put(CH_STATUS_REQUEST, spec); shc.handshakeExtensions.put(SSLExtension.CH_STATUS_REQUEST, spec);
if (!shc.isResumption && if (!shc.isResumption &&
!shc.negotiatedProtocol.useTLS13PlusSpec()) { !shc.negotiatedProtocol.useTLS13PlusSpec()) {
shc.handshakeProducers.put(SSLHandshake.CERTIFICATE_STATUS.id, shc.handshakeProducers.put(SSLHandshake.CERTIFICATE_STATUS.id,
@ -654,13 +651,12 @@ final class CertStatusExtension {
// In response to "status_request" extension request only. // In response to "status_request" extension request only.
CertStatusRequestSpec spec = (CertStatusRequestSpec) CertStatusRequestSpec spec = (CertStatusRequestSpec)
shc.handshakeExtensions.get(CH_STATUS_REQUEST); shc.handshakeExtensions.get(SSLExtension.CH_STATUS_REQUEST);
if (spec == null) { if (spec == null) {
// Ignore, no status_request extension requested. // Ignore, no status_request extension requested.
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
SSLLogger.finest( SSLLogger.finest("Ignore unavailable extension: " +
"Ignore unavailable extension: " + SSLExtension.CH_STATUS_REQUEST.name);
CH_STATUS_REQUEST.name);
} }
return null; // ignore the extension return null; // ignore the extension
@ -681,8 +677,8 @@ final class CertStatusExtension {
byte[] extData = new byte[0]; byte[] extData = new byte[0];
// Update the context. // Update the context.
shc.handshakeExtensions.put( shc.handshakeExtensions.put(SSLExtension.SH_STATUS_REQUEST,
SH_STATUS_REQUEST, CertStatusRequestSpec.DEFAULT); CertStatusRequestSpec.DEFAULT);
return extData; return extData;
} }
@ -708,7 +704,7 @@ final class CertStatusExtension {
// In response to "status_request" extension request only. // In response to "status_request" extension request only.
CertStatusRequestSpec requestedCsr = (CertStatusRequestSpec) CertStatusRequestSpec requestedCsr = (CertStatusRequestSpec)
chc.handshakeExtensions.get(CH_STATUS_REQUEST); chc.handshakeExtensions.get(SSLExtension.CH_STATUS_REQUEST);
if (requestedCsr == null) { if (requestedCsr == null) {
throw chc.conContext.fatal(Alert.UNEXPECTED_MESSAGE, throw chc.conContext.fatal(Alert.UNEXPECTED_MESSAGE,
"Unexpected status_request extension in ServerHello"); "Unexpected status_request extension in ServerHello");
@ -722,8 +718,8 @@ final class CertStatusExtension {
} }
// Update the context. // Update the context.
chc.handshakeExtensions.put( chc.handshakeExtensions.put(SSLExtension.SH_STATUS_REQUEST,
SH_STATUS_REQUEST, CertStatusRequestSpec.DEFAULT); CertStatusRequestSpec.DEFAULT);
// Since we've received a legitimate status_request in the // Since we've received a legitimate status_request in the
// ServerHello, stapling is active if it's been enabled. // ServerHello, stapling is active if it's been enabled.
@ -909,7 +905,7 @@ final class CertStatusExtension {
return null; return null;
} }
if (!chc.sslConfig.isAvailable(CH_STATUS_REQUEST_V2)) { if (!chc.sslConfig.isAvailable(SSLExtension.CH_STATUS_REQUEST_V2)) {
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
SSLLogger.finest( SSLLogger.finest(
"Ignore unavailable status_request_v2 extension"); "Ignore unavailable status_request_v2 extension");
@ -926,8 +922,8 @@ final class CertStatusExtension {
0x00, 0x07, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00}; 0x00, 0x07, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00};
// Update the context. // Update the context.
chc.handshakeExtensions.put( chc.handshakeExtensions.put(SSLExtension.CH_STATUS_REQUEST_V2,
CH_STATUS_REQUEST_V2, CertStatusRequestV2Spec.DEFAULT); CertStatusRequestV2Spec.DEFAULT);
return extData; return extData;
} }
@ -951,7 +947,7 @@ final class CertStatusExtension {
// The consuming happens in server side only. // The consuming happens in server side only.
ServerHandshakeContext shc = (ServerHandshakeContext)context; ServerHandshakeContext shc = (ServerHandshakeContext)context;
if (!shc.sslConfig.isAvailable(CH_STATUS_REQUEST_V2)) { if (!shc.sslConfig.isAvailable(SSLExtension.CH_STATUS_REQUEST_V2)) {
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
SSLLogger.finest( SSLLogger.finest(
"Ignore unavailable status_request_v2 extension"); "Ignore unavailable status_request_v2 extension");
@ -969,7 +965,8 @@ final class CertStatusExtension {
} }
// Update the context. // Update the context.
shc.handshakeExtensions.put(CH_STATUS_REQUEST_V2, spec); shc.handshakeExtensions.put(SSLExtension.CH_STATUS_REQUEST_V2,
spec);
if (!shc.isResumption) { if (!shc.isResumption) {
shc.handshakeProducers.putIfAbsent( shc.handshakeProducers.putIfAbsent(
SSLHandshake.CERTIFICATE_STATUS.id, SSLHandshake.CERTIFICATE_STATUS.id,
@ -1013,7 +1010,7 @@ final class CertStatusExtension {
// In response to "status_request_v2" extension request only // In response to "status_request_v2" extension request only
CertStatusRequestV2Spec spec = (CertStatusRequestV2Spec) CertStatusRequestV2Spec spec = (CertStatusRequestV2Spec)
shc.handshakeExtensions.get(CH_STATUS_REQUEST_V2); shc.handshakeExtensions.get(SSLExtension.CH_STATUS_REQUEST_V2);
if (spec == null) { if (spec == null) {
// Ignore, no status_request_v2 extension requested. // Ignore, no status_request_v2 extension requested.
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
@ -1038,8 +1035,8 @@ final class CertStatusExtension {
byte[] extData = new byte[0]; byte[] extData = new byte[0];
// Update the context. // Update the context.
shc.handshakeExtensions.put( shc.handshakeExtensions.put(SSLExtension.SH_STATUS_REQUEST_V2,
SH_STATUS_REQUEST_V2, CertStatusRequestV2Spec.DEFAULT); CertStatusRequestV2Spec.DEFAULT);
return extData; return extData;
} }
@ -1065,7 +1062,7 @@ final class CertStatusExtension {
// In response to "status_request" extension request only // In response to "status_request" extension request only
CertStatusRequestV2Spec requestedCsr = (CertStatusRequestV2Spec) CertStatusRequestV2Spec requestedCsr = (CertStatusRequestV2Spec)
chc.handshakeExtensions.get(CH_STATUS_REQUEST_V2); chc.handshakeExtensions.get(SSLExtension.CH_STATUS_REQUEST_V2);
if (requestedCsr == null) { if (requestedCsr == null) {
throw chc.conContext.fatal(Alert.UNEXPECTED_MESSAGE, throw chc.conContext.fatal(Alert.UNEXPECTED_MESSAGE,
"Unexpected status_request_v2 extension in ServerHello"); "Unexpected status_request_v2 extension in ServerHello");
@ -1079,8 +1076,8 @@ final class CertStatusExtension {
} }
// Update the context. // Update the context.
chc.handshakeExtensions.put( chc.handshakeExtensions.put(SSLExtension.SH_STATUS_REQUEST_V2,
SH_STATUS_REQUEST_V2, CertStatusRequestV2Spec.DEFAULT); CertStatusRequestV2Spec.DEFAULT);
// Since we've received a legitimate status_request in the // Since we've received a legitimate status_request in the
// ServerHello, stapling is active if it's been enabled. If it // ServerHello, stapling is active if it's been enabled. If it

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -113,7 +113,6 @@ enum SSLExtension implements SSLStringizer {
null, null,
null, null,
CertStatusExtension.certStatusReqStringizer), CertStatusExtension.certStatusReqStringizer),
CR_STATUS_REQUEST (0x0005, "status_request"), CR_STATUS_REQUEST (0x0005, "status_request"),
CT_STATUS_REQUEST (0x0005, "status_request", CT_STATUS_REQUEST (0x0005, "status_request",
SSLHandshake.CERTIFICATE, SSLHandshake.CERTIFICATE,
@ -124,6 +123,7 @@ enum SSLExtension implements SSLStringizer {
null, null,
null, null,
CertStatusExtension.certStatusRespStringizer), CertStatusExtension.certStatusRespStringizer),
// extensions defined in RFC 4681 // extensions defined in RFC 4681
USER_MAPPING (0x0006, "user_mapping"), USER_MAPPING (0x0006, "user_mapping"),
@ -554,6 +554,16 @@ enum SSLExtension implements SSLStringizer {
return null; return null;
} }
static String nameOf(int extensionType) {
for (SSLExtension ext : SSLExtension.values()) {
if (ext.id == extensionType) {
return ext.name;
}
}
return "unknown extension";
}
static boolean isConsumable(int extensionType) { static boolean isConsumable(int extensionType) {
for (SSLExtension ext : SSLExtension.values()) { for (SSLExtension ext : SSLExtension.values()) {
if (ext.id == extensionType && if (ext.id == extensionType &&

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2018, 2020 Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -86,11 +86,14 @@ final class SSLExtensions {
"Received buggy supported_groups extension " + "Received buggy supported_groups extension " +
"in the ServerHello handshake message"); "in the ServerHello handshake message");
} }
} else { } else if (handshakeType == SSLHandshake.SERVER_HELLO) {
throw hm.handshakeContext.conContext.fatal( throw hm.handshakeContext.conContext.fatal(
Alert.UNSUPPORTED_EXTENSION, Alert.UNSUPPORTED_EXTENSION, "extension (" +
"extension (" + extId + extId + ") should not be presented in " +
") should not be presented in " + handshakeType.name); handshakeType.name);
} else {
isSupported = false;
// debug log to ignore unknown extension for handshakeType
} }
} }
@ -365,9 +368,10 @@ final class SSLExtensions {
} }
private static String toString(int extId, byte[] extData) { private static String toString(int extId, byte[] extData) {
String extName = SSLExtension.nameOf(extId);
MessageFormat messageFormat = new MessageFormat( MessageFormat messageFormat = new MessageFormat(
"\"unknown extension ({0})\": '{'\n" + "\"{0} ({1})\": '{'\n" +
"{1}\n" + "{2}\n" +
"'}'", "'}'",
Locale.ENGLISH); Locale.ENGLISH);
@ -375,6 +379,7 @@ final class SSLExtensions {
String encoded = hexEncoder.encodeBuffer(extData); String encoded = hexEncoder.encodeBuffer(extData);
Object[] messageFields = { Object[] messageFields = {
extName,
extId, extId,
Utilities.indent(encoded) Utilities.indent(encoded)
}; };