Further review comments from Brad

This commit is contained in:
Seán Coffey 2026-02-05 14:07:16 +00:00
parent c36775d586
commit 555321150c
3 changed files with 68 additions and 90 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2026, 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
@ -1018,13 +1018,18 @@ final class CertificateMessage {
.stream()
.map(ss -> ss.keyAlgorithm)
.distinct()
.filter(ka -> SignatureScheme.getPreferableAlgorithm( // Don't select a signature scheme unless
hc.algorithmConstraints, // we will be able to produce
hc.peerRequestedSignatureSchemes, // a CertificateVerify message later
.filter(ka -> SignatureScheme.getPreferableAlgorithm(
// Don't select a signature scheme unless
// we will be able to produce a
// CertificateVerify message later
hc.algorithmConstraints,
hc.peerRequestedSignatureSchemes,
ka, hc.negotiatedProtocol) != null
|| SSLLogger.logWarning(SSLLogger.Opt.HANDSHAKE,
"Unable to produce CertificateVerify for key algorithm: " + ka))
.filter(ka -> X509Authentication.valueOfKeyAlgorithm(ka) != null
"Unable to produce CertificateVerify for " +
"key algorithm: " + ka))
.filter(ka ->
X509Authentication.valueOfKeyAlgorithm(ka) != null
|| SSLLogger.logWarning(SSLLogger.Opt.HANDSHAKE,
"Unsupported key algorithm: " + ka))
.toArray(String[]::new);
@ -1118,7 +1123,7 @@ final class CertificateMessage {
if (hc.handshakeConsumers.containsKey(
SSLHandshake.ENCRYPTED_EXTENSIONS.id)) {
throw hc.conContext.fatal(Alert.UNEXPECTED_MESSAGE,
"Unexpected Certificate handshake message");
"Unexpected Certificate handshake message");
}
T13CertificateMessage cm = new T13CertificateMessage(hc, message);
@ -1382,5 +1387,4 @@ final class CertificateMessage {
return alert;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2026, 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
@ -33,6 +33,7 @@ import javax.crypto.BadPaddingException;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLProtocolException;
import sun.security.ssl.SSLCipher.SSLReadCipher;
import static sun.security.ssl.SSLLogger.Opt.*;
/**
* DTLS {@code InputRecord} implementation for {@code SSLEngine}.
@ -125,7 +126,7 @@ final class DTLSInputRecord extends InputRecord implements DTLSRecord {
return null;
}
if (SSLLogger.isOn() && SSLLogger.isOn(SSLLogger.Opt.RECORD_PACKET)) {
if (SSLLogger.isOn() && SSLLogger.isOn(RECORD_PACKET)) {
SSLLogger.fine("Raw read", packet);
}
@ -150,7 +151,7 @@ final class DTLSInputRecord extends InputRecord implements DTLSRecord {
int contentLen = ((packet.get() & 0xFF) << 8) |
(packet.get() & 0xFF); // pos: 11, 12
if (SSLLogger.isOn() && SSLLogger.isOn(SSLLogger.Opt.RECORD)) {
if (SSLLogger.isOn() && SSLLogger.isOn(RECORD)) {
SSLLogger.fine("READ: " +
ProtocolVersion.nameOf(majorVersion, minorVersion) +
" " + ContentType.nameOf(contentType) + ", length = " +
@ -162,7 +163,7 @@ final class DTLSInputRecord extends InputRecord implements DTLSRecord {
if (this.readEpoch > recordEpoch) {
// Reset the position of the packet buffer.
packet.position(recLim);
if (SSLLogger.isOn() && SSLLogger.isOn(SSLLogger.Opt.RECORD)) {
if (SSLLogger.isOn() && SSLLogger.isOn(RECORD)) {
SSLLogger.fine("READ: discard this old record", recordEnS);
}
return null;
@ -181,8 +182,7 @@ final class DTLSInputRecord extends InputRecord implements DTLSRecord {
packet.position(recLim);
if (SSLLogger.isOn() &&
SSLLogger.isOn(SSLLogger.Opt.HANDSHAKE_VERBOSE)) {
if (SSLLogger.isOn() && SSLLogger.isOn(HANDSHAKE_VERBOSE)) {
SSLLogger.fine("Premature record (epoch), discard it.");
}
@ -224,7 +224,7 @@ final class DTLSInputRecord extends InputRecord implements DTLSRecord {
plaintextFragment = plaintext.fragment;
contentType = plaintext.contentType;
} catch (GeneralSecurityException gse) {
if (SSLLogger.isOn() && SSLLogger.isOn(SSLLogger.Opt.SSL)) {
if (SSLLogger.isOn() && SSLLogger.isOn(SSL)) {
SSLLogger.fine("Discard invalid record: " + gse);
}
@ -242,8 +242,7 @@ final class DTLSInputRecord extends InputRecord implements DTLSRecord {
// Cleanup the handshake reassembler if necessary.
if ((reassembler != null) &&
(reassembler.handshakeEpoch < recordEpoch)) {
if (SSLLogger.isOn() &&
SSLLogger.isOn(SSLLogger.Opt.HANDSHAKE_VERBOSE)) {
if (SSLLogger.isOn() && SSLLogger.isOn(HANDSHAKE_VERBOSE)) {
SSLLogger.fine("Cleanup the handshake reassembler");
}
@ -275,8 +274,7 @@ final class DTLSInputRecord extends InputRecord implements DTLSRecord {
if (hsFrag == null) {
// invalid, discard this record
if (SSLLogger.isOn() &&
SSLLogger.isOn(SSLLogger.Opt.HANDSHAKE_VERBOSE)) {
if (SSLLogger.isOn() && SSLLogger.isOn(HANDSHAKE_VERBOSE)) {
SSLLogger.fine(
"Invalid handshake message, discard it.");
}
@ -299,8 +297,7 @@ final class DTLSInputRecord extends InputRecord implements DTLSRecord {
return pt == null ? null : new Plaintext[] { pt };
}
if (SSLLogger.isOn() &&
SSLLogger.isOn(SSLLogger.Opt.HANDSHAKE_VERBOSE)) {
if (SSLLogger.isOn() && SSLLogger.isOn(HANDSHAKE_VERBOSE)) {
SSLLogger.fine("The reassembler is not initialized yet.");
}
@ -360,7 +357,7 @@ final class DTLSInputRecord extends InputRecord implements DTLSRecord {
int remaining = plaintextFragment.remaining();
if (remaining < handshakeHeaderSize) {
if (SSLLogger.isOn() && SSLLogger.isOn(SSLLogger.Opt.SSL)) {
if (SSLLogger.isOn() && SSLLogger.isOn(SSL)) {
SSLLogger.fine("Discard invalid record: " +
"too small record to hold a handshake fragment");
}
@ -372,7 +369,7 @@ final class DTLSInputRecord extends InputRecord implements DTLSRecord {
// Fail fast for unknown handshake message.
byte handshakeType = plaintextFragment.get(); // pos: 0
if (!SSLHandshake.isKnown(handshakeType)) {
if (SSLLogger.isOn() && SSLLogger.isOn(SSLLogger.Opt.SSL)) {
if (SSLLogger.isOn() && SSLLogger.isOn(SSL)) {
SSLLogger.fine("Discard invalid record: " +
"unknown handshake type size, Handshake.msg_type = " +
(handshakeType & 0xFF));
@ -408,7 +405,7 @@ final class DTLSInputRecord extends InputRecord implements DTLSRecord {
((plaintextFragment.get() & 0xFF) << 8) |
(plaintextFragment.get() & 0xFF); // pos: 9-11
if ((remaining - handshakeHeaderSize) < fragmentLength) {
if (SSLLogger.isOn() && SSLLogger.isOn(SSLLogger.Opt.SSL)) {
if (SSLLogger.isOn() && SSLLogger.isOn(SSL)) {
SSLLogger.fine("Discard invalid record: " +
"not a complete handshake fragment in the record");
}
@ -752,8 +749,7 @@ final class DTLSInputRecord extends InputRecord implements DTLSRecord {
// It's OK to discard retransmission as the handshake hash
// is computed as if each handshake message had been sent
// as a single fragment.
if (SSLLogger.isOn() &&
SSLLogger.isOn(SSLLogger.Opt.HANDSHAKE_VERBOSE)) {
if (SSLLogger.isOn() && SSLLogger.isOn(HANDSHAKE_VERBOSE)) {
SSLLogger.fine("Have got the full message, discard it.");
}
@ -772,10 +768,10 @@ final class DTLSInputRecord extends InputRecord implements DTLSRecord {
}
// The ranges SHOULD NOT overlap.
if (hole.offset > hsf.fragmentOffset || hole.limit < fragmentLimit) {
if (hole.offset > hsf.fragmentOffset ||
hole.limit < fragmentLimit) {
if (SSLLogger.isOn() &&
SSLLogger.isOn(SSLLogger.Opt.SSL)) {
if (SSLLogger.isOn() && SSLLogger.isOn(SSL)) {
SSLLogger.fine("Discard invalid record: " +
"handshake fragment ranges are overlapping");
}
@ -843,10 +839,10 @@ final class DTLSInputRecord extends InputRecord implements DTLSRecord {
}
// Read the random (32 bytes)
if (fragmentData.remaining() < 32) {
if (SSLLogger.isOn() &&
SSLLogger.isOn(SSLLogger.Opt.RECORD)) {
SSLLogger.fine("Rejected client hello fragment (bad random len) " +
"fo=" + hsf.fragmentOffset + " fl=" + hsf.fragmentLength);
if (SSLLogger.isOn() && SSLLogger.isOn(HANDSHAKE_VERBOSE)) {
SSLLogger.fine("Rejected client hello fragment" +
"(bad random len) fo=" +
hsf.fragmentOffset + " fl=" + hsf.fragmentLength);
}
return null;
}
@ -868,10 +864,10 @@ final class DTLSInputRecord extends InputRecord implements DTLSRecord {
// Cookie
byte[] cookie = Record.getBytes8(fragmentData);
if (firstHello && cookie.length != 0) {
if (SSLLogger.isOn() &&
SSLLogger.isOn(SSLLogger.Opt.RECORD)) {
SSLLogger.fine("Rejected initial client hello fragment (bad cookie len) " +
"fo=" + hsf.fragmentOffset + " fl=" + hsf.fragmentLength);
if (SSLLogger.isOn() && SSLLogger.isOn(HANDSHAKE_VERBOSE)) {
SSLLogger.fine("Rejected initial client hello " +
" fragment (bad cookie len) fo=" +
hsf.fragmentOffset + " fl=" + hsf.fragmentLength);
}
return null;
}
@ -905,9 +901,10 @@ final class DTLSInputRecord extends InputRecord implements DTLSRecord {
}
}
} catch (IOException ioe) {
if (SSLLogger.isOn() && SSLLogger.isOn(SSLLogger.Opt.RECORD)) {
if (SSLLogger.isOn() && SSLLogger.isOn(HANDSHAKE_VERBOSE)) {
SSLLogger.fine("Rejected client hello fragment " +
"fo=" + hsf.fragmentOffset + " fl=" + hsf.fragmentLength);
"fo=" + hsf.fragmentOffset + " fl=" +
hsf.fragmentLength);
}
return null;
}
@ -1037,8 +1034,7 @@ final class DTLSInputRecord extends InputRecord implements DTLSRecord {
int previousEpoch = nextRecordEpoch - 1;
if (rf.recordEpoch < previousEpoch) {
// Too old to use, discard this record.
if (SSLLogger.isOn() &&
SSLLogger.isOn(SSLLogger.Opt.HANDSHAKE_VERBOSE)) {
if (SSLLogger.isOn() && SSLLogger.isOn(HANDSHAKE_VERBOSE)) {
SSLLogger.fine(
"Too old epoch to use this record, discard it.");
}
@ -1084,8 +1080,7 @@ final class DTLSInputRecord extends InputRecord implements DTLSRecord {
if (!isDesired) {
// Too old to use, discard this retransmitted record
if (SSLLogger.isOn() &&
SSLLogger.isOn(SSLLogger.Opt.HANDSHAKE_VERBOSE)) {
if (SSLLogger.isOn() && SSLLogger.isOn(HANDSHAKE_VERBOSE)) {
SSLLogger.fine(
"Too old retransmission to use, discard it.");
}
@ -1098,8 +1093,7 @@ final class DTLSInputRecord extends InputRecord implements DTLSRecord {
// Previously disordered record for the current epoch.
//
// Should have been retransmitted. Discard this record.
if (SSLLogger.isOn() &&
SSLLogger.isOn(SSLLogger.Opt.HANDSHAKE_VERBOSE)) {
if (SSLLogger.isOn() && SSLLogger.isOn(HANDSHAKE_VERBOSE)) {
SSLLogger.fine(
"Lagging behind record (sequence), discard it.");
}
@ -1137,8 +1131,7 @@ final class DTLSInputRecord extends InputRecord implements DTLSRecord {
Plaintext acquirePlaintext() throws SSLProtocolException {
if (bufferedFragments.isEmpty()) {
if (SSLLogger.isOn() &&
SSLLogger.isOn(SSLLogger.Opt.HANDSHAKE_VERBOSE)) {
if (SSLLogger.isOn() && SSLLogger.isOn(HANDSHAKE_VERBOSE)) {
SSLLogger.fine("No received handshake messages");
}
return null;
@ -1160,7 +1153,7 @@ final class DTLSInputRecord extends InputRecord implements DTLSRecord {
resetHandshakeFlight(precedingFlight);
if (SSLLogger.isOn() &&
SSLLogger.isOn(SSLLogger.Opt.HANDSHAKE_VERBOSE)) {
SSLLogger.isOn(HANDSHAKE_VERBOSE)) {
SSLLogger.fine("Received a retransmission flight.");
}
@ -1172,8 +1165,7 @@ final class DTLSInputRecord extends InputRecord implements DTLSRecord {
}
if (!flightIsReady) {
if (SSLLogger.isOn() &&
SSLLogger.isOn(SSLLogger.Opt.HANDSHAKE_VERBOSE)) {
if (SSLLogger.isOn() && SSLLogger.isOn(HANDSHAKE_VERBOSE)) {
SSLLogger.fine(
"The handshake flight is not ready to use: " +
handshakeFlight.handshakeType);
@ -1258,8 +1250,7 @@ final class DTLSInputRecord extends InputRecord implements DTLSRecord {
if (readEpoch != rFrag.recordEpoch) {
if (readEpoch > rFrag.recordEpoch) {
// discard old records
if (SSLLogger.isOn() &&
SSLLogger.isOn(SSLLogger.Opt.HANDSHAKE_VERBOSE)) {
if (SSLLogger.isOn() && SSLLogger.isOn(HANDSHAKE_VERBOSE)) {
SSLLogger.fine(
"Discard old buffered ciphertext fragments.");
}
@ -1271,8 +1262,7 @@ final class DTLSInputRecord extends InputRecord implements DTLSRecord {
flightIsReady = false;
}
if (SSLLogger.isOn() &&
SSLLogger.isOn(SSLLogger.Opt.HANDSHAKE_VERBOSE)) {
if (SSLLogger.isOn() && SSLLogger.isOn(HANDSHAKE_VERBOSE)) {
SSLLogger.fine(
"Not yet ready to decrypt the cached fragments.");
}
@ -1289,8 +1279,7 @@ final class DTLSInputRecord extends InputRecord implements DTLSRecord {
plaintextFragment = plaintext.fragment;
rFrag.contentType = plaintext.contentType;
} catch (GeneralSecurityException gse) {
if (SSLLogger.isOn() &&
SSLLogger.isOn(SSLLogger.Opt.HANDSHAKE_VERBOSE)) {
if (SSLLogger.isOn() && SSLLogger.isOn(HANDSHAKE_VERBOSE)) {
SSLLogger.fine("Discard invalid record: ", gse);
}
@ -1313,7 +1302,7 @@ final class DTLSInputRecord extends InputRecord implements DTLSRecord {
if (hsFrag == null) {
// invalid, discard this record
if (SSLLogger.isOn() &&
SSLLogger.isOn(SSLLogger.Opt.HANDSHAKE_VERBOSE)) {
SSLLogger.isOn(HANDSHAKE_VERBOSE)) {
SSLLogger.fine(
"Invalid handshake fragment, discard it",
plaintextFragment);
@ -1464,8 +1453,7 @@ final class DTLSInputRecord extends InputRecord implements DTLSRecord {
if (expectCCSFlight) {
// Have the ChangeCipherSpec/Finished flight been received?
boolean isReady = hasFinishedMessage();
if (SSLLogger.isOn() &&
SSLLogger.isOn(SSLLogger.Opt.HANDSHAKE_VERBOSE)) {
if (SSLLogger.isOn() && SSLLogger.isOn(HANDSHAKE_VERBOSE)) {
SSLLogger.fine(
"Has the final flight been received? " + isReady);
}
@ -1473,8 +1461,7 @@ final class DTLSInputRecord extends InputRecord implements DTLSRecord {
return isReady;
}
if (SSLLogger.isOn() &&
SSLLogger.isOn(SSLLogger.Opt.HANDSHAKE_VERBOSE)) {
if (SSLLogger.isOn() && SSLLogger.isOn(HANDSHAKE_VERBOSE)) {
SSLLogger.fine("No flight is received yet.");
}
@ -1487,8 +1474,7 @@ final class DTLSInputRecord extends InputRecord implements DTLSRecord {
// single handshake message flight
boolean isReady = hasCompleted(flightType);
if (SSLLogger.isOn() &&
SSLLogger.isOn(SSLLogger.Opt.HANDSHAKE_VERBOSE)) {
if (SSLLogger.isOn() && SSLLogger.isOn(HANDSHAKE_VERBOSE)) {
SSLLogger.fine(
"Is the handshake message completed? " + isReady);
}
@ -1502,8 +1488,7 @@ final class DTLSInputRecord extends InputRecord implements DTLSRecord {
if (flightType == SSLHandshake.SERVER_HELLO.id) {
// Firstly, check the first flight handshake message.
if (!hasCompleted(flightType)) {
if (SSLLogger.isOn() &&
SSLLogger.isOn(SSLLogger.Opt.HANDSHAKE_VERBOSE)) {
if (SSLLogger.isOn() && SSLLogger.isOn(HANDSHAKE_VERBOSE)) {
SSLLogger.fine(
"The ServerHello message is not completed yet.");
}
@ -1515,8 +1500,7 @@ final class DTLSInputRecord extends InputRecord implements DTLSRecord {
// an abbreviated handshake
//
if (hasFinishedMessage()) {
if (SSLLogger.isOn() &&
SSLLogger.isOn(SSLLogger.Opt.HANDSHAKE_VERBOSE)) {
if (SSLLogger.isOn() && SSLLogger.isOn(HANDSHAKE_VERBOSE)) {
SSLLogger.fine("It's an abbreviated handshake.");
}
@ -1530,8 +1514,7 @@ final class DTLSInputRecord extends InputRecord implements DTLSRecord {
SSLHandshake.SERVER_HELLO_DONE.id);
if ((holes == null) || !holes.isEmpty()) {
// Not yet got the final message of the flight.
if (SSLLogger.isOn() &&
SSLLogger.isOn(SSLLogger.Opt.HANDSHAKE_VERBOSE)) {
if (SSLLogger.isOn() && SSLLogger.isOn(HANDSHAKE_VERBOSE)) {
SSLLogger.fine(
"Not yet got the ServerHelloDone message");
}
@ -1543,8 +1526,7 @@ final class DTLSInputRecord extends InputRecord implements DTLSRecord {
boolean isReady = hasCompleted(bufferedFragments,
handshakeFlight.minMessageSeq,
handshakeFlight.maxMessageSeq);
if (SSLLogger.isOn() &&
SSLLogger.isOn(SSLLogger.Opt.HANDSHAKE_VERBOSE)) {
if (SSLLogger.isOn() && SSLLogger.isOn(HANDSHAKE_VERBOSE)) {
SSLLogger.fine(
"Is the ServerHello flight (message " +
handshakeFlight.minMessageSeq + "-" +
@ -1567,8 +1549,7 @@ final class DTLSInputRecord extends InputRecord implements DTLSRecord {
// Firstly, check the first flight handshake message.
if (!hasCompleted(flightType)) {
if (SSLLogger.isOn() &&
SSLLogger.isOn(SSLLogger.Opt.HANDSHAKE_VERBOSE)) {
if (SSLLogger.isOn() && SSLLogger.isOn(HANDSHAKE_VERBOSE)) {
SSLLogger.fine(
"The ClientKeyExchange or client Certificate " +
"message is not completed yet.");
@ -1583,7 +1564,7 @@ final class DTLSInputRecord extends InputRecord implements DTLSRecord {
!hasCompleted(SSLHandshake.CERTIFICATE_VERIFY.id)) {
if (SSLLogger.isOn() &&
SSLLogger.isOn(SSLLogger.Opt.HANDSHAKE_VERBOSE)) {
SSLLogger.isOn(HANDSHAKE_VERBOSE)) {
SSLLogger.fine(
"Not yet have the CertificateVerify message");
}
@ -1594,8 +1575,7 @@ final class DTLSInputRecord extends InputRecord implements DTLSRecord {
if (!hasFinishedMessage()) {
// not yet have the ChangeCipherSpec/Finished messages
if (SSLLogger.isOn() &&
SSLLogger.isOn(SSLLogger.Opt.HANDSHAKE_VERBOSE)) {
if (SSLLogger.isOn() && SSLLogger.isOn(HANDSHAKE_VERBOSE)) {
SSLLogger.fine(
"Not yet have the ChangeCipherSpec and " +
"Finished messages");
@ -1608,8 +1588,7 @@ final class DTLSInputRecord extends InputRecord implements DTLSRecord {
boolean isReady = hasCompleted(bufferedFragments,
handshakeFlight.minMessageSeq,
handshakeFlight.maxMessageSeq);
if (SSLLogger.isOn() &&
SSLLogger.isOn(SSLLogger.Opt.HANDSHAKE_VERBOSE)) {
if (SSLLogger.isOn() && SSLLogger.isOn(HANDSHAKE_VERBOSE)) {
SSLLogger.fine(
"Is the ClientKeyExchange flight (message " +
handshakeFlight.minMessageSeq + "-" +
@ -1623,8 +1602,7 @@ final class DTLSInputRecord extends InputRecord implements DTLSRecord {
//
// Otherwise, need to receive more handshake messages.
//
if (SSLLogger.isOn() &&
SSLLogger.isOn(SSLLogger.Opt.HANDSHAKE_VERBOSE)) {
if (SSLLogger.isOn() && SSLLogger.isOn(HANDSHAKE_VERBOSE)) {
SSLLogger.fine("Need to receive more handshake messages");
}
@ -1645,9 +1623,6 @@ final class DTLSInputRecord extends InputRecord implements DTLSRecord {
for (RecordFragment fragment : bufferedFragments) {
if (fragment.contentType == ContentType.CHANGE_CIPHER_SPEC.id) {
if (hasFin) {
return true;
}
hasCCS = true;
} else if (fragment.contentType == ContentType.HANDSHAKE.id
&& fragment.isCiphertext) {
@ -1774,4 +1749,3 @@ final class DTLSInputRecord extends InputRecord implements DTLSRecord {
}
}
}

View File

@ -206,9 +206,8 @@ public final class SSLLogger implements System.Logger {
System.err.printf("%-16s %s%n%n", "expand",
"expanded (less compact) output format");
System.err.printf("%-16s %s%n", "all", "turn on all debugging");
System.err.printf("%-16s %s%n", "ssl", "turn on ssl debugging");
System.err.println();
System.err.println("The following filters can be used with ssl:");
System.err.printf("%-16s %s%n%n", "ssl", "turn on ssl debugging");
System.err.printf("The following filters can be used with ssl:%n%n");
System.err.printf(" %-14s %s%n", "defaultctx",
"print default SSL initialization");
System.err.printf(" %-14s %s%n", "handshake",
@ -234,9 +233,10 @@ public final class SSLLogger implements System.Logger {
System.err.printf(" %-14s %s%n", "trustmanager",
"print trust manager tracing");
System.err.printf("%nIf \"ssl\" is specified by itself," +
" all non-widening filters are enabled.%n%n");
System.err.printf("%nAdding valid filter options to \"ssl\" will log" +
" messages to include%njust those filtered categories.%n");
" all non-widening filters are enabled.%n");
System.err.printf("%nSpecifying filter options with \"ssl\"" +
" includes messages for the selected categories, as well" +
" as all general SSL debug messages.%n");
System.exit(0);
}