Skip to content

Commit 2d37395

Browse files
committed
Add support to pick the server cert by specified alias
1 parent 849bcb0 commit 2d37395

File tree

2 files changed

+93
-1
lines changed

2 files changed

+93
-1
lines changed
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
/*
2+
* Copyright (c) 2025, WSO2 LLC. (http://www.wso2.com).
3+
*
4+
* WSO2 LLC. licenses this file to you under the Apache License,
5+
* Version 2.0 (the "License"); you may not use this file except
6+
* in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing,
12+
* software distributed under the License is distributed on an
13+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
* KIND, either express or implied. See the License for the
15+
* specific language governing permissions and limitations
16+
* under the License.
17+
*/
18+
19+
package org.apache.synapse.transport.nhttp.config;
20+
21+
import javax.net.ssl.SSLEngine;
22+
import javax.net.ssl.X509ExtendedKeyManager;
23+
import javax.net.ssl.X509KeyManager;
24+
import java.net.Socket;
25+
import java.security.Principal;
26+
import java.security.PrivateKey;
27+
import java.security.cert.X509Certificate;
28+
import java.util.Arrays;
29+
30+
/**
31+
* Custom X509KeyManager that selects a specific alias for client and server certificates
32+
*/
33+
public class AliasBasedKeyManager extends X509ExtendedKeyManager {
34+
private final X509KeyManager keyManager;
35+
private final String preferredKeyAlias;
36+
37+
public AliasBasedKeyManager(X509KeyManager keyManager, String preferredKeyAlias) {
38+
this.keyManager = keyManager;
39+
this.preferredKeyAlias = preferredKeyAlias;
40+
}
41+
42+
@Override
43+
public String[] getClientAliases(String keyType, Principal[] issuers) {
44+
return keyManager.getClientAliases(keyType, issuers);
45+
}
46+
47+
@Override
48+
public String chooseClientAlias(String[] keyType, Principal[] issuers, Socket socket) {
49+
return keyManager.chooseClientAlias(keyType, issuers, socket);
50+
}
51+
52+
@Override
53+
public String[] getServerAliases(String keyType, Principal[] issuers) {
54+
return keyManager.getServerAliases(keyType, issuers);
55+
}
56+
57+
@Override
58+
public String chooseServerAlias(String keyType, Principal[] issuers, Socket socket) {
59+
String[] aliases = keyManager.getServerAliases(keyType, issuers);
60+
if (aliases != null && Arrays.asList(aliases).contains(preferredKeyAlias)) {
61+
return preferredKeyAlias;
62+
}
63+
return keyManager.chooseServerAlias(keyType, issuers, socket);
64+
}
65+
66+
@Override
67+
public String chooseEngineServerAlias(String keyType, Principal[] issuers, SSLEngine engine) {
68+
return chooseServerAlias(keyType, issuers, (Socket) null);
69+
}
70+
71+
@Override
72+
public X509Certificate[] getCertificateChain(String alias) {
73+
return keyManager.getCertificateChain(alias);
74+
}
75+
76+
@Override
77+
public PrivateKey getPrivateKey(String alias) {
78+
return keyManager.getPrivateKey(alias);
79+
}
80+
}

modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/nhttp/config/ServerConnFactoryBuilder.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,8 @@ protected SSLContextDetails createSSLContext(
126126
String type = getValueOfElementWithLocalName(keyStoreEl,"Type");
127127
OMElement storePasswordEl = keyStoreEl.getFirstChildWithName(new QName("Password"));
128128
OMElement keyPasswordEl = keyStoreEl.getFirstChildWithName(new QName("KeyPassword"));
129+
OMElement aliasEl = keyStoreEl.getFirstChildWithName(new QName("ServerCertificateAlias"));
130+
String requiredAlias = aliasEl != null ? StringUtils.trimToNull(aliasEl.getText()) : null;
129131
if (storePasswordEl == null) {
130132
throw new AxisFault("Cannot proceed because Password element is missing in KeyStore");
131133
}
@@ -148,7 +150,17 @@ protected SSLContextDetails createSSLContext(
148150
KeyManagerFactory kmfactory = KeyManagerFactory.getInstance(
149151
KeyManagerFactory.getDefaultAlgorithm());
150152
kmfactory.init(keyStore, keyPassword.toCharArray());
151-
keymanagers = kmfactory.getKeyManagers();
153+
if (requiredAlias != null) {
154+
KeyManager[] keyManagers = kmfactory.getKeyManagers();
155+
for (int i = 0; i < keyManagers.length; i++) {
156+
if (keyManagers[i] instanceof X509KeyManager) {
157+
keyManagers[i] = new AliasBasedKeyManager((X509KeyManager) keyManagers[i], requiredAlias);
158+
}
159+
}
160+
keymanagers = keyManagers;
161+
} else {
162+
keymanagers = kmfactory.getKeyManagers();
163+
}
152164
if (log.isInfoEnabled() && keymanagers != null) {
153165
for (KeyManager keymanager: keymanagers) {
154166
if (keymanager instanceof X509KeyManager) {

0 commit comments

Comments
 (0)