F-11870: handle unrecognized RDN types in WolfSSLX509 DN reformatting
parent
33d3adcef7
commit
ea8aa7a49b
|
|
@ -698,7 +698,7 @@ public class WolfSSLX509 extends X509Certificate {
|
|||
private String[] DNs = { "/emailAddress=", "/CN=", "/OU=",
|
||||
"/O=", "/L=", "/ST=", "/C="};
|
||||
|
||||
/* replace the wolfSSL version of the tag. Returns replacement
|
||||
/* Replace the wolfSSL version of the tag. Returns replacement
|
||||
* on success. */
|
||||
private String getReplace(String in) {
|
||||
if (in.equals("/emailAddress=")) {
|
||||
|
|
@ -725,53 +725,51 @@ public class WolfSSLX509 extends X509Certificate {
|
|||
return null;
|
||||
}
|
||||
|
||||
/* check if the string starts with an expected tag.
|
||||
* returns index into DNs of tag when found */
|
||||
private int containsDN(String in) {
|
||||
int i;
|
||||
for (i = 0; i < DNs.length; i++) {
|
||||
if (in.startsWith(DNs[i]))
|
||||
return i;
|
||||
/* Map "TAG=value" component to its JSSE spelling, leaving
|
||||
* unrecognized tags unchanged. */
|
||||
private String mapComponent(String component) {
|
||||
for (int i = 0; i < DNs.length; i++) {
|
||||
/* DNs entries carry a leading '/', drop it to compare */
|
||||
String tag = DNs[i].substring(1);
|
||||
if (component.startsWith(tag)) {
|
||||
String replace = getReplace(DNs[i]);
|
||||
if (replace != null) {
|
||||
return replace.concat(
|
||||
component.substring(tag.length()));
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
return component;
|
||||
}
|
||||
|
||||
/* convert name from having "/DN=" format to "DN= ," format
|
||||
/* Convert name from having "/DN=" format to "DN= ," format
|
||||
* returns the new reformatted string on success */
|
||||
private String reformatList(String in) {
|
||||
String[] ret;
|
||||
int i, j;
|
||||
String tmp = in;
|
||||
ArrayList<String> list = new ArrayList<String>();
|
||||
|
||||
if (in == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
ret = in.split("/");
|
||||
|
||||
while (tmp.length() > 3) {
|
||||
for (i = tmp.length() - 3; i >= 0; i--) {
|
||||
if ((j = containsDN(in.substring(i))) >= 0) {
|
||||
String current = tmp.substring(i, tmp.length());
|
||||
current = current.replaceAll(DNs[j],
|
||||
getReplace(DNs[j]));
|
||||
list.add(current);
|
||||
tmp = tmp.substring(0, i);
|
||||
break;
|
||||
}
|
||||
/* Split before each '/' followed by a "TAG=" attribute type,
|
||||
* then reverse the RDN order. wolfSSL does not escape '/', so
|
||||
* '/' inside a value followed by "TAG=" will split too.
|
||||
* Unrecognized RDN types pass through unchanged. */
|
||||
String[] parts = in.split("/(?=[A-Za-z0-9.]+=)");
|
||||
ArrayList<String> list = new ArrayList<String>();
|
||||
for (int i = 0; i < parts.length; i++) {
|
||||
if (!parts[i].isEmpty()) {
|
||||
list.add(mapComponent(parts[i]));
|
||||
}
|
||||
}
|
||||
|
||||
ret = list.toArray(new String[list.size()]);
|
||||
tmp = "";
|
||||
for (i = 0; i < ret.length - 1; i++) {
|
||||
tmp = tmp.concat(ret[i]);
|
||||
tmp = tmp.concat(", ");
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = list.size() - 1; i >= 0; i--) {
|
||||
sb.append(list.get(i));
|
||||
if (i > 0) {
|
||||
sb.append(", ");
|
||||
}
|
||||
}
|
||||
tmp = tmp.concat(ret[i]);
|
||||
|
||||
return tmp;
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private WolfSSLPrincipal(String in) {
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ import java.security.cert.CertificateException;
|
|||
import java.security.cert.CertificateExpiredException;
|
||||
import java.security.cert.CertificateNotYetValidException;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.Base64;
|
||||
import java.util.Date;
|
||||
import java.util.Set;
|
||||
import java.util.List;
|
||||
|
|
@ -116,6 +117,62 @@ public class WolfSSLX509Test {
|
|||
subjectDN = x509.getSubjectDN();
|
||||
}
|
||||
|
||||
/* Self-signed cert whose subject and issuer use DC (domainComponent)
|
||||
* RDNs, an attribute type outside the reformat tag table.
|
||||
* DN: DC=com, DC=example, CN=test.example.com */
|
||||
private static final String DC_RDN_CERT_DER =
|
||||
"MIIDczCCAlugAwIBAgIUJvqgr93mm9aonQB+pyzrjyu7TBowDQYJKoZIhvcN" +
|
||||
"AQELBQAwSTETMBEGCgmSJomT8ixkARkWA2NvbTEXMBUGCgmSJomT8ixkARkW" +
|
||||
"B2V4YW1wbGUxGTAXBgNVBAMMEHRlc3QuZXhhbXBsZS5jb20wHhcNMjYwODI0" +
|
||||
"MjA0NjUyWhcNMzYwODIxMjA0NjUyWjBJMRMwEQYKCZImiZPyLGQBGRYDY29t" +
|
||||
"MRcwFQYKCZImiZPyLGQBGRYHZXhhbXBsZTEZMBcGA1UEAwwQdGVzdC5leGFt" +
|
||||
"cGxlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALAo9F5Q" +
|
||||
"xsEOHMFK0sNiHi5HUscCQWtFxA5AlH9mqfgSAYbEpm9YmHbvgBH2Mvc5vEZY" +
|
||||
"hB1CRQT7pipS4iXUG+7cnz7M8YyKUuh5TtQTIARaPu2ZpTHOxQ2QMip/eHsI" +
|
||||
"l8IggiVZZuJcnXHj1nrB8pcx4wreXyi+7r7INViffNV61bGOes6ftIH/sptD" +
|
||||
"Sw0CXQUf1KfiM1rXaXw8cezYmmJWFoie0R6tbrMEfTRAKb1j4IEqWa3e7Krq" +
|
||||
"+bZEmiw5kfP2vlEW2w+TylNWOm7uQu742VAJnIqgZ3nnVPxqd/5Ef5E8sMmI" +
|
||||
"Xy/F+rhEFxZtmAiDnBflmPypXSp0w5c01P0CAwEAAaNTMFEwHQYDVR0OBBYE" +
|
||||
"FPHoxpJFtgM3/ntZjdyu3Zy2CtSnMB8GA1UdIwQYMBaAFPHoxpJFtgM3/ntZ" +
|
||||
"jdyu3Zy2CtSnMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEB" +
|
||||
"AJvFrnuTfU9MNTRCJGM3JAyex5RK3g5/SOs6uBjM8A1oM5NzTuZrjQzFWMtd" +
|
||||
"srS8HMIoatKOxGYJUU1OHy4JpfF6Rfv38+q6QuugemIGmDjBEqmO100ZoYgF" +
|
||||
"ppujEABELIyMpvqp48e6U8uo1mRoK8BWp4KeZiPo7jzi32HoDkeu+ZUNvn1G" +
|
||||
"0DwgDiYl5ailSofBKplprpI77hx11fypekatWqsfR01Q/0OEkSsj/gO50em1" +
|
||||
"VAMUYB1v8WXAivovfkUjx+J8xaund6Tx595jTHMOpQMckM/4C2ecvmixEKrF" +
|
||||
"uz8gim9WCP+Pe6WZI948Kia+btaslCf58Y6/qrgJTJE=";
|
||||
|
||||
@Test
|
||||
public void testGetSubjectIssuerDNUnrecognizedRdnTerminates()
|
||||
throws Exception {
|
||||
|
||||
Assume.assumeTrue(WolfSSL.RsaEnabled());
|
||||
|
||||
byte[] der = Base64.getDecoder().decode(DC_RDN_CERT_DER);
|
||||
final WolfSSLX509 cert = new WolfSSLX509(der);
|
||||
|
||||
/* Reversed DN, matching getSubjectX500Principal() output. */
|
||||
final String expected = "CN=test.example.com, DC=example, DC=com";
|
||||
final String[] result = new String[2];
|
||||
|
||||
/* Run in a worker thread so a non-terminating reformat shows up as
|
||||
* a still-alive thread instead of hanging the whole test run. */
|
||||
Thread worker = new Thread(new Runnable() {
|
||||
public void run() {
|
||||
result[0] = cert.getSubjectDN().getName();
|
||||
result[1] = cert.getIssuerDN().getName();
|
||||
}
|
||||
});
|
||||
worker.setDaemon(true);
|
||||
worker.start();
|
||||
worker.join(5000);
|
||||
|
||||
assertFalse("getSubjectDN/getIssuerDN did not terminate on an " +
|
||||
"unrecognized RDN type", worker.isAlive());
|
||||
assertEquals(expected, result[0]);
|
||||
assertEquals(expected, result[1]);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testServerParsing() {
|
||||
try {
|
||||
|
|
|
|||
Loading…
Reference in New Issue