Lines 27-42
import java.security.PrivateKey;
Link Here
|
27 |
import java.security.UnrecoverableKeyException; |
27 |
import java.security.UnrecoverableKeyException; |
28 |
import java.security.cert.Certificate; |
28 |
import java.security.cert.Certificate; |
29 |
import java.security.cert.CertificateException; |
29 |
import java.security.cert.CertificateException; |
|
|
30 |
import java.security.cert.CertificateParsingException; |
30 |
import java.security.cert.X509Certificate; |
31 |
import java.security.cert.X509Certificate; |
31 |
import java.util.ArrayList; |
32 |
import java.util.ArrayList; |
32 |
import java.util.Arrays; |
33 |
import java.util.Arrays; |
|
|
34 |
import java.util.Collection; |
33 |
import java.util.Enumeration; |
35 |
import java.util.Enumeration; |
34 |
import java.util.HashMap; |
36 |
import java.util.HashMap; |
35 |
import java.util.List; |
37 |
import java.util.List; |
36 |
import java.util.Map; |
38 |
import java.util.Map; |
37 |
import java.util.Objects; |
39 |
import java.util.Objects; |
|
|
40 |
import java.util.stream.Collectors; |
38 |
|
41 |
|
|
|
42 |
import org.apache.commons.codec.binary.Hex; |
39 |
import org.apache.commons.lang3.StringUtils; |
43 |
import org.apache.commons.lang3.StringUtils; |
|
|
44 |
import org.apache.commons.lang3.tuple.Pair; |
40 |
import org.apache.jmeter.threads.JMeterContextService; |
45 |
import org.apache.jmeter.threads.JMeterContextService; |
41 |
import org.slf4j.Logger; |
46 |
import org.slf4j.Logger; |
42 |
import org.slf4j.LoggerFactory; |
47 |
import org.slf4j.LoggerFactory; |
Lines 113-118
public final class JmeterKeyStore {
Link Here
|
113 |
this.certsByAlias = new HashMap<>(); |
118 |
this.certsByAlias = new HashMap<>(); |
114 |
|
119 |
|
115 |
PrivateKey privateKey = null; |
120 |
PrivateKey privateKey = null; |
|
|
121 |
if (log.isDebugEnabled()) { |
122 |
logDetailsOnKeystore(store); |
123 |
} |
116 |
int index = 0; |
124 |
int index = 0; |
117 |
Enumeration<String> aliases = store.aliases(); |
125 |
Enumeration<String> aliases = store.aliases(); |
118 |
while (aliases.hasMoreElements()) { |
126 |
while (aliases.hasMoreElements()) { |
Lines 148-153
public final class JmeterKeyStore {
Link Here
|
148 |
this.names = aliasesList.toArray(new String[aliasesList.size()]); |
156 |
this.names = aliasesList.toArray(new String[aliasesList.size()]); |
149 |
} |
157 |
} |
150 |
|
158 |
|
|
|
159 |
private static final Map<String, String> EXTENDED_KEY_USAGES = new HashMap<>(); |
160 |
static { |
161 |
EXTENDED_KEY_USAGES.put("1.3.6.1.4.1.311.10.3.4", "Can use encrypted file systems (EFS) (EFS_CRYPTO)"); |
162 |
EXTENDED_KEY_USAGES.put("1.3.6.1.4.1.311.10.3.4.1", "Can use encrypted file systems (EFS) (EFS_RECOVERY)"); |
163 |
EXTENDED_KEY_USAGES.put("1.3.6.1.4.1.311.20.2.2", "Smartcard logon to Microsoft Windows"); |
164 |
EXTENDED_KEY_USAGES.put("1.3.6.1.5.5.7.3.1", |
165 |
"Transport Layer Security (TLS) World Wide Web (WWW) server authentication"); |
166 |
EXTENDED_KEY_USAGES.put("1.3.6.1.5.5.7.3.2", |
167 |
"Transport Layer Security (TLS) World Wide Web (WWW) client authentication"); |
168 |
EXTENDED_KEY_USAGES.put("1.3.6.1.5.5.7.3.3", "Signing of downloadable executable code"); |
169 |
EXTENDED_KEY_USAGES.put("1.3.6.1.5.5.7.3.4", "Email protection"); |
170 |
EXTENDED_KEY_USAGES.put("1.3.6.1.5.5.7.3.5", "IP security end system"); |
171 |
EXTENDED_KEY_USAGES.put("1.3.6.1.5.5.7.3.6", "IP security tunnel termination"); |
172 |
EXTENDED_KEY_USAGES.put("1.3.6.1.5.5.7.3.7", "IP security user"); |
173 |
EXTENDED_KEY_USAGES.put("1.3.6.1.5.5.7.3.8", "Time stamping"); |
174 |
EXTENDED_KEY_USAGES.put("1.3.6.1.5.5.7.3.9", "Signing Online Certificate Status Protocol (OCSP) responses"); |
175 |
EXTENDED_KEY_USAGES.put("2.5.29.37.0", "Any purpose"); |
176 |
} |
177 |
|
178 |
private static final List<String> SAN_GENERAL_NAMES = Arrays.asList("otherName", "rfc822Name", "dNSName", "x400Address", |
179 |
"directoryName", "ediPartyName", "uniformResourceIdentifier", "iPAddress", "registeredID"); |
180 |
|
181 |
private void logDetailsOnKeystore(KeyStore keystore) { |
182 |
Enumeration<String> aliases; |
183 |
try { |
184 |
aliases = keystore.aliases(); |
185 |
} catch (KeyStoreException e) { |
186 |
log.debug("Problem reading the aliases from the store {}", keystore, e); |
187 |
return; |
188 |
} |
189 |
int i = 1; |
190 |
while(aliases.hasMoreElements()) { |
191 |
String alias = aliases.nextElement(); |
192 |
log.debug("Certificate at index {} with alias {}:", i++, alias); |
193 |
X509Certificate cert; |
194 |
try { |
195 |
cert = (X509Certificate) keystore.getCertificate(alias); |
196 |
} catch (KeyStoreException e) { |
197 |
log.debug("Can't read certificate for alias {}", alias, e); |
198 |
continue; |
199 |
} |
200 |
log.debug("Subject DN: {}", cert.getSubjectX500Principal()); |
201 |
log.debug("Issuer DN: {}", cert.getIssuerX500Principal()); |
202 |
log.debug("Not valid before: {}", cert.getNotBefore().toInstant()); |
203 |
log.debug("Not valid after: {}", cert.getNotAfter().toInstant()); |
204 |
try { |
205 |
final Collection<List<?>> subjectAlternativeNames = cert.getSubjectAlternativeNames(); |
206 |
if (!(subjectAlternativeNames == null || subjectAlternativeNames.isEmpty())) { |
207 |
log.debug("SAN: {}", decodeSanList(subjectAlternativeNames)); |
208 |
} |
209 |
} catch (CertificateParsingException e) { |
210 |
log.debug("Problem parsing SAN for alias {}", alias, e); |
211 |
} |
212 |
List<String> extendedKeyUsage; |
213 |
try { |
214 |
extendedKeyUsage = cert.getExtendedKeyUsage(); |
215 |
if (extendedKeyUsage != null) { |
216 |
for (String keyUsage : extendedKeyUsage) { |
217 |
log.debug("Extended Key Usage: {} ({})", EXTENDED_KEY_USAGES.getOrDefault(keyUsage, keyUsage), |
218 |
keyUsage); |
219 |
} |
220 |
} |
221 |
} catch (CertificateParsingException e) { |
222 |
log.debug("Can't get extendedKeyUsage for alias {}", alias, e); |
223 |
} |
224 |
} |
225 |
} |
226 |
|
227 |
private String decodeSanList(Collection<List<?>> subjectAlternativeNames) { |
228 |
List<Pair<String, String>> decodedEntries = new ArrayList<>(); |
229 |
for (List<?> entry : subjectAlternativeNames) { |
230 |
Object indexData = entry.get(0); |
231 |
Object data = entry.get(1); |
232 |
if (indexData instanceof Integer) { |
233 |
Integer generalNameIndex = (Integer) indexData; |
234 |
String description = sanGeneralNameIndexToName(generalNameIndex); |
235 |
String valueString = sanDataToString(data); |
236 |
decodedEntries.add(Pair.of(description, valueString)); |
237 |
} |
238 |
} |
239 |
return decodedEntries.stream() |
240 |
.map(e -> e.getKey() + ": " + e.getValue()) |
241 |
.collect(Collectors.joining(", ")); |
242 |
} |
243 |
|
244 |
private String sanDataToString(Object data) { |
245 |
if (data instanceof String) { |
246 |
return (String) data; |
247 |
} |
248 |
return Hex.encodeHexString((byte[]) data); |
249 |
} |
250 |
|
251 |
private String sanGeneralNameIndexToName(Integer index) { |
252 |
String description; |
253 |
if (index < SAN_GENERAL_NAMES.size()) { |
254 |
description = SAN_GENERAL_NAMES.get(index); |
255 |
} else { |
256 |
description = "UNKNOWN_SAN_GENERAL_NAME"; |
257 |
} |
258 |
return description; |
259 |
} |
260 |
|
151 |
private X509Certificate[] toX509Certificates(Certificate[] chain) { |
261 |
private X509Certificate[] toX509Certificates(Certificate[] chain) { |
152 |
X509Certificate[] x509certs = new X509Certificate[chain.length]; |
262 |
X509Certificate[] x509certs = new X509Certificate[chain.length]; |
153 |
for (int i = 0; i < x509certs.length; i++) { |
263 |
for (int i = 0; i < x509certs.length; i++) { |
154 |
- |
|
|