Skip to content

Commit 1a9d178

Browse files
committed
Fix AliasX509ExtendedKeyManager to process both server and client aliases properly
Signed-off-by: Stéphane Gobancé <19359548+ecnabogs@users.noreply.github.com>
1 parent 0a84ebf commit 1a9d178

File tree

2 files changed

+335
-16
lines changed

2 files changed

+335
-16
lines changed

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

+60-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,50 @@ 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+
163+
/**
164+
* Gets this key manager's alias if it matches the given key algorithm and has
165+
* been issued by any of the specified issuers (might be {@code null}, meaning
166+
* issuer does not matter) otherwise returns an {@link Optional#empty() empty
167+
* result }.
168+
* @param keyType the required key algorithm.
169+
* @param issuers the list of acceptable CA issuer subject names or {@code null}
170+
* if it does not matter which issuers are used.
171+
* @param finder the function to find the underlying available key aliases.
172+
* @return this key manager's alias if appropriate or an empty result otherwise.
173+
*/
174+
private Optional<String> findFirstMatchingAlias(String keyType, Principal[] issuers, KeyAliasFinder finder) {
175+
return findFirstMatchingAlias(new String[] { keyType }, issuers, finder);
176+
}
177+
178+
/**
179+
* Gets this key manager's alias if it matches any of the given key algorithms and
180+
* has been issued by any of the specified issuers (might be {@code null}, meaning
181+
* issuer does not matter) otherwise returns an {@link Optional#empty() empty
182+
* result }.
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+
}
199+
147200
}
148201

149202
}

0 commit comments

Comments
 (0)