@@ -479,6 +479,11 @@ private void unload()
479
479
_certWilds .clear ();
480
480
}
481
481
482
+ Map <String , X509 > aliasCerts ()
483
+ {
484
+ return _aliasX509 ;
485
+ }
486
+
482
487
@ ManagedAttribute (value = "The selected TLS protocol versions" , readonly = true )
483
488
public String [] getSelectedProtocols ()
484
489
{
@@ -2118,7 +2123,7 @@ public String toString()
2118
2123
_trustStoreResource );
2119
2124
}
2120
2125
2121
- class Factory
2126
+ private static class Factory
2122
2127
{
2123
2128
private final KeyStore _keyStore ;
2124
2129
private final KeyStore _trustStore ;
@@ -2133,7 +2138,7 @@ class Factory
2133
2138
}
2134
2139
}
2135
2140
2136
- class AliasSNIMatcher extends SNIMatcher
2141
+ static class AliasSNIMatcher extends SNIMatcher
2137
2142
{
2138
2143
private String _host ;
2139
2144
@@ -2235,11 +2240,17 @@ public void setNeedClientAuth(boolean needClientAuth)
2235
2240
}
2236
2241
2237
2242
/**
2238
- * Does the default {@link #sniSelect(String, Principal[], SSLSession, String, Collection)} implementation
2239
- * require an SNI match? Note that if a non SNI handshake is accepted, requests may still be rejected
2240
- * at the HTTP level for incorrect SNI (see SecureRequestCustomizer).
2241
- * @return true if no SNI match is handled as no certificate match, false if no SNI match is handled by
2242
- * delegation to the non SNI matching methods.
2243
+ * <p>Returns whether an SNI match is required when choosing the alias that
2244
+ * identifies the certificate to send to the client.</p>
2245
+ * <p>The exact logic to choose an alias given the SNI is configurable via
2246
+ * {@link #setSNISelector(SniX509ExtendedKeyManager.SniSelector)}.</p>
2247
+ * <p>The default implementation is {@link #sniSelect(String, Principal[], SSLSession, String, Collection)}
2248
+ * and if SNI is not required it will delegate the TLS implementation to
2249
+ * choose an alias (typically the first alias in the KeyStore).</p>
2250
+ * <p>Note that if a non SNI handshake is accepted, requests may still be rejected
2251
+ * at the HTTP level for incorrect SNI (see SecureRequestCustomizer).</p>
2252
+ *
2253
+ * @return whether an SNI match is required when choosing the alias that identifies the certificate
2243
2254
*/
2244
2255
@ ManagedAttribute ("Whether the TLS handshake is rejected if there is no SNI host match" )
2245
2256
public boolean isSniRequired ()
@@ -2248,13 +2259,12 @@ public boolean isSniRequired()
2248
2259
}
2249
2260
2250
2261
/**
2251
- * Set if the default {@link #sniSelect(String, Principal[], SSLSession, String, Collection)} implementation
2252
- * require an SNI match? Note that if a non SNI handshake is accepted, requests may still be rejected
2253
- * at the HTTP level for incorrect SNI (see SecureRequestCustomizer).
2254
- * This setting may have no effect if {@link #sniSelect(String, Principal[], SSLSession, String, Collection)} is
2255
- * overridden or a non null function is passed to {@link #setSNISelector(SniX509ExtendedKeyManager.SniSelector)}.
2256
- * @param sniRequired true if no SNI match is handled as no certificate match, false if no SNI match is handled by
2257
- * delegation to the non SNI matching methods.
2262
+ * <p>Sets whether an SNI match is required when choosing the alias that
2263
+ * identifies the certificate to send to the client.</p>
2264
+ * <p>This setting may have no effect if {@link #sniSelect(String, Principal[], SSLSession, String, Collection)} is
2265
+ * overridden or a custom function is passed to {@link #setSNISelector(SniX509ExtendedKeyManager.SniSelector)}.</p>
2266
+ *
2267
+ * @param sniRequired whether an SNI match is required when choosing the alias that identifies the certificate
2258
2268
*/
2259
2269
public void setSniRequired (boolean sniRequired )
2260
2270
{
@@ -2297,7 +2307,7 @@ public String sniSelect(String keyType, Principal[] issuers, SSLSession session,
2297
2307
if (sniHost == null )
2298
2308
{
2299
2309
// No SNI, so reject or delegate.
2300
- return _sniRequired ? null : SniX509ExtendedKeyManager .SniSelector .DELEGATE ;
2310
+ return isSniRequired () ? null : SniX509ExtendedKeyManager .SniSelector .DELEGATE ;
2301
2311
}
2302
2312
else
2303
2313
{
@@ -2306,9 +2316,15 @@ public String sniSelect(String keyType, Principal[] issuers, SSLSession session,
2306
2316
.filter (x509 -> x509 .matches (sniHost ))
2307
2317
.collect (Collectors .toList ());
2308
2318
2309
- // No match, let the JDK decide unless unmatched SNIs are rejected.
2310
2319
if (matching .isEmpty ())
2311
- return isSniRequired () ? null : SniX509ExtendedKeyManager .SniSelector .DELEGATE ;
2320
+ {
2321
+ // There is no match for this SNI among the certificates valid for
2322
+ // this keyType; check if there is any certificate that matches this
2323
+ // SNI, as we will likely be called again with a different keyType.
2324
+ boolean anyMatching = aliasCerts ().values ().stream ()
2325
+ .anyMatch (x509 -> x509 .matches (sniHost ));
2326
+ return isSniRequired () || anyMatching ? null : SniX509ExtendedKeyManager .SniSelector .DELEGATE ;
2327
+ }
2312
2328
2313
2329
String alias = matching .get (0 ).getAlias ();
2314
2330
if (matching .size () == 1 )
0 commit comments