Commit 465fdd5d authored by Guus der Kinderen's avatar Guus der Kinderen

OF-1100: Fix parsing of 'otherName' records

This commit formalizes the parsing of subjectAltName certificate extensions.
parent 910dc255
......@@ -2,7 +2,6 @@ package org.jivesoftware.util;
import org.bouncycastle.asn1.*;
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.asn1.x509.BasicConstraints;
import org.bouncycastle.asn1.x509.Extension;
import org.bouncycastle.asn1.x509.GeneralName;
import org.bouncycastle.asn1.x509.GeneralNames;
......@@ -14,7 +13,6 @@ import org.bouncycastle.operator.ContentSigner;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
import org.junit.BeforeClass;
import org.junit.Test;
import sun.security.x509.SubjectAlternativeNameExtension;
import java.math.BigInteger;
import java.security.KeyPair;
......@@ -29,11 +27,14 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
/**
* Created by guus on 3-3-16.
* Unit test to validate the functionality of @{link CertificateManager}.
*
* @author Guus der Kinderen, guus@goodbytes.nl
*/
public class CertificateManagerTest
{
public static final ASN1ObjectIdentifier XMPP_ADDR_OID = new ASN1ObjectIdentifier( "1.3.6.1.5.5.7.8.5" );
public static final ASN1ObjectIdentifier DNS_SRV_OID = new ASN1ObjectIdentifier( "1.3.6.1.5.5.7.8.7" );
private static KeyPairGenerator keyPairGenerator;
private static KeyPair subjectKeyPair;
......@@ -49,7 +50,6 @@ public class CertificateManagerTest
subjectKeyPair = keyPairGenerator.generateKeyPair();
issuerKeyPair = keyPairGenerator.generateKeyPair();
contentSigner = new JcaContentSignerBuilder( "SHA1withRSA" ).build( issuerKeyPair.getPrivate() );
}
/**
......@@ -117,11 +117,9 @@ public class CertificateManagerTest
subjectKeyPair.getPublic()
);
final DERTaggedObject derTaggedDomainName = new DERTaggedObject(0, new DERUTF8String(subjectAltNameXmppAddr) );
final DLSequence otherName = new DLSequence(new ASN1Encodable[]{XMPP_ADDR_OID, derTaggedDomainName});
final GeneralNames generalNames = new GeneralNames(new GeneralName(GeneralName.otherName, otherName));
builder.addExtension( Extension.subjectAlternativeName, false, generalNames );
final DERSequence otherName = new DERSequence( new ASN1Encodable[] { XMPP_ADDR_OID, new DERUTF8String( subjectAltNameXmppAddr ) });
final GeneralNames subjectAltNames = new GeneralNames( new GeneralName(GeneralName.otherName, otherName ) );
builder.addExtension( Extension.subjectAlternativeName, true, subjectAltNames );
final X509CertificateHolder certificateHolder = builder.build( contentSigner );
final X509Certificate cert = new JcaX509CertificateConverter().getCertificate( certificateHolder );
......@@ -135,6 +133,51 @@ public class CertificateManagerTest
assertFalse( serverIdentities.contains( subjectCommonName ) );
}
/**
* {@link CertificateManager#getServerIdentities(X509Certificate)} should return:
* <ul>
* <li>the 'DNS SRV' subjectAltName value</li>
* <li>explicitly not the Common Name</li>
* </ul>
*
* when a certificate contains:
* <ul>
* <li>a subjectAltName entry of type otherName with an ASN.1 Object Identifier of "id-on-dnsSRV"</li>
* </ul>
*/
@Test
public void testServerIdentitiesDnsSrv() throws Exception
{
// Setup fixture.
final String subjectCommonName = "MySubjectCommonName";
final String subjectAltNameDnsSrv = "MySubjectAltNameXmppAddr";
final X509v3CertificateBuilder builder = new JcaX509v3CertificateBuilder(
new X500Name( "CN=MyIssuer" ), // Issuer
BigInteger.valueOf( Math.abs( new SecureRandom().nextInt() ) ), // Random serial number
new Date( System.currentTimeMillis() - ( 1000L * 60 * 60 * 24 * 30 ) ), // Not before 30 days ago
new Date( System.currentTimeMillis() + ( 1000L * 60 * 60 * 24 * 99 ) ), // Not after 99 days from now
new X500Name( "CN=" + subjectCommonName ), // Subject
subjectKeyPair.getPublic()
);
final DERSequence otherName = new DERSequence( new ASN1Encodable[] {DNS_SRV_OID, new DERUTF8String( "_xmpp-server."+subjectAltNameDnsSrv ) });
final GeneralNames subjectAltNames = new GeneralNames( new GeneralName(GeneralName.otherName, otherName ) );
builder.addExtension( Extension.subjectAlternativeName, true, subjectAltNames );
final X509CertificateHolder certificateHolder = builder.build( contentSigner );
final X509Certificate cert = new JcaX509CertificateConverter().getCertificate( certificateHolder );
// Execute system under test
final List<String> serverIdentities = CertificateManager.getServerIdentities( cert );
// Verify result
assertEquals( 1, serverIdentities.size() );
assertTrue( serverIdentities.contains( subjectAltNameDnsSrv ));
assertFalse( serverIdentities.contains( subjectCommonName ) );
}
/**
* {@link CertificateManager#getServerIdentities(X509Certificate)} should return:
* <ul>
......@@ -210,14 +253,12 @@ public class CertificateManagerTest
subjectKeyPair.getPublic()
);
final DERTaggedObject derTaggedDomainName = new DERTaggedObject(0, new DERUTF8String(subjectAltNameXmppAddr) );
final DLSequence otherName = new DLSequence(new ASN1Encodable[]{XMPP_ADDR_OID, derTaggedDomainName});
final GeneralNames generalNames = new GeneralNames( new GeneralName[] {
new GeneralName(GeneralName.otherName, otherName),
new GeneralName(GeneralName.dNSName, subjectAltNameDNS)
final DERSequence otherName = new DERSequence( new ASN1Encodable[] { XMPP_ADDR_OID, new DERUTF8String( subjectAltNameXmppAddr ) });
final GeneralNames subjectAltNames = new GeneralNames( new GeneralName[] {
new GeneralName( GeneralName.otherName, otherName ),
new GeneralName( GeneralName.dNSName, subjectAltNameDNS )
});
builder.addExtension( Extension.subjectAlternativeName, false, generalNames );
builder.addExtension( Extension.subjectAlternativeName, true, subjectAltNames );
final X509CertificateHolder certificateHolder = builder.build( contentSigner );
final X509Certificate cert = new JcaX509CertificateConverter().getCertificate( certificateHolder );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment