Skip to content

Commit 6ace75c

Browse files
committed
Fix AliasX509ExtendedKeyManager to process both server and client aliases properly
1 parent 0a84ebf commit 6ace75c

File tree

2 files changed

+324
-16
lines changed

2 files changed

+324
-16
lines changed

spring-boot-project/spring-boot/src/main/java/org/springframework/boot/ssl/AliasKeyManagerFactory.java

+59-7
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@
2626
import java.security.UnrecoverableKeyException;
2727
import java.security.cert.X509Certificate;
2828
import java.util.Arrays;
29+
import java.util.Objects;
30+
import java.util.Optional;
31+
import java.util.function.BiFunction;
32+
import java.util.stream.Stream;
2933

3034
import javax.net.ssl.KeyManager;
3135
import javax.net.ssl.KeyManagerFactory;
@@ -42,6 +46,7 @@
4246
* {@link KeyManagerFactory#getKeyManagers()} is final.
4347
*
4448
* @author Scott Frederick
49+
* @author Stéphane Gobancé
4550
*/
4651
final class AliasKeyManagerFactory extends KeyManagerFactory {
4752

@@ -105,23 +110,27 @@ private AliasX509ExtendedKeyManager(X509ExtendedKeyManager keyManager, String al
105110
}
106111

107112
@Override
108-
public String chooseEngineClientAlias(String[] strings, Principal[] principals, SSLEngine sslEngine) {
109-
return this.delegate.chooseEngineClientAlias(strings, principals, sslEngine);
113+
public String chooseEngineClientAlias(String[] keyTypes, Principal[] issuers, SSLEngine sslEngine) {
114+
return findFirstMatchingAlias(keyTypes, issuers, this::getClientAliases)
115+
.orElseGet(() -> this.delegate.chooseEngineClientAlias(keyTypes, issuers, sslEngine));
110116
}
111117

112118
@Override
113-
public String chooseEngineServerAlias(String s, Principal[] principals, SSLEngine sslEngine) {
114-
return this.alias;
119+
public String chooseEngineServerAlias(String keyType, Principal[] issuers, SSLEngine sslEngine) {
120+
return findFirstMatchingAlias(keyType, issuers, this::getServerAliases)
121+
.orElseGet(() -> this.delegate.chooseEngineServerAlias(keyType, issuers, sslEngine));
115122
}
116123

117124
@Override
118-
public String chooseClientAlias(String[] keyType, Principal[] issuers, Socket socket) {
119-
return this.delegate.chooseClientAlias(keyType, issuers, socket);
125+
public String chooseClientAlias(String[] keyTypes, Principal[] issuers, Socket socket) {
126+
return findFirstMatchingAlias(keyTypes, issuers, this::getClientAliases)
127+
.orElseGet(() -> this.delegate.chooseClientAlias(keyTypes, issuers, socket));
120128
}
121129

122130
@Override
123131
public String chooseServerAlias(String keyType, Principal[] issuers, Socket socket) {
124-
return this.delegate.chooseServerAlias(keyType, issuers, socket);
132+
return findFirstMatchingAlias(keyType, issuers, this::getServerAliases)
133+
.orElseGet(() -> this.delegate.chooseServerAlias(keyType, issuers, socket));
125134
}
126135

127136
@Override
@@ -144,6 +153,49 @@ public String[] getServerAliases(String keyType, Principal[] issuers) {
144153
return this.delegate.getServerAliases(keyType, issuers);
145154
}
146155

156+
/**
157+
* Typed-BiFunction for better readability.
158+
*/
159+
private interface KeyAliasFinder extends BiFunction<String, Principal[], String[]> {}
160+
161+
/**
162+
* Gets this key manager's alias if it matches the given key algorithm and has
163+
* been issued by any of the specified issuers (might be {@code null}, meaning
164+
* issuer does not matter) otherwise returns an {@link Optional#empty() empty
165+
* result }.
166+
*
167+
* @param keyType the required key algorithm.
168+
* @param issuers the list of acceptable CA issuer subject names or {@code null}
169+
* if it does not matter which issuers are used.
170+
* @param finder the function to find the underlying available key aliases.
171+
* @return this key manager's alias if appropriate or an empty result otherwise.
172+
*/
173+
private Optional<String> findFirstMatchingAlias(String keyType, Principal[] issuers, KeyAliasFinder finder) {
174+
return findFirstMatchingAlias(new String[] { keyType }, issuers, finder);
175+
}
176+
177+
/**
178+
* Gets this key manager's alias if it matches any of the given key algorithms and
179+
* has been issued by any of the specified issuers (might be {@code null}, meaning
180+
* issuer does not matter) otherwise returns an {@link Optional#empty() empty
181+
* result }.
182+
*
183+
* @param keyTypes the required key algorithms.
184+
* @param issuers the list of acceptable CA issuer subject names or {@code null}
185+
* if it does not matter which issuers are used.
186+
* @param finder the function to find the underlying available key aliases.
187+
* @return this key manager's alias if appropriate or an empty result otherwise.
188+
*/
189+
private Optional<String> findFirstMatchingAlias(String[] keyTypes, Principal[] issuers, KeyAliasFinder finder) {
190+
return Optional.ofNullable(keyTypes)
191+
.flatMap(types -> Stream.of(types)
192+
.filter(Objects::nonNull)
193+
.map(type -> finder.apply(type, issuers))
194+
.filter(Objects::nonNull)
195+
.flatMap(Stream::of)
196+
.filter(this.alias::equals)
197+
.findFirst());
198+
}
147199
}
148200

149201
}

0 commit comments

Comments
 (0)