You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by er...@apache.org on 2007/09/30 03:24:46 UTC

svn commit: r580663 - in /directory/sandbox/erodriguez/kerberos-pkinit/src: main/java/org/apache/directory/server/kerberos/pkinit/certs/ test/java/org/apache/directory/server/kerberos/pkinit/certs/

Author: erodriguez
Date: Sat Sep 29 18:24:45 2007
New Revision: 580663

URL: http://svn.apache.org/viewvc?rev=580663&view=rev
Log:
Added TestCase and classes for supporting test PKI, required for testing PKINIT programmatically, ie without hardware such as SmartCards.

Added:
    directory/sandbox/erodriguez/kerberos-pkinit/src/main/java/org/apache/directory/server/kerberos/pkinit/certs/
    directory/sandbox/erodriguez/kerberos-pkinit/src/main/java/org/apache/directory/server/kerberos/pkinit/certs/CertificateChainFactory.java   (with props)
    directory/sandbox/erodriguez/kerberos-pkinit/src/main/java/org/apache/directory/server/kerberos/pkinit/certs/EndEntityGenerator.java   (with props)
    directory/sandbox/erodriguez/kerberos-pkinit/src/main/java/org/apache/directory/server/kerberos/pkinit/certs/IntermediateCaGenerator.java   (with props)
    directory/sandbox/erodriguez/kerberos-pkinit/src/main/java/org/apache/directory/server/kerberos/pkinit/certs/KeyPairSpec.java   (with props)
    directory/sandbox/erodriguez/kerberos-pkinit/src/main/java/org/apache/directory/server/kerberos/pkinit/certs/TrustAnchorGenerator.java   (with props)
    directory/sandbox/erodriguez/kerberos-pkinit/src/test/java/org/apache/directory/server/kerberos/pkinit/certs/
    directory/sandbox/erodriguez/kerberos-pkinit/src/test/java/org/apache/directory/server/kerberos/pkinit/certs/CertificateChainFactoryTest.java   (with props)

Added: directory/sandbox/erodriguez/kerberos-pkinit/src/main/java/org/apache/directory/server/kerberos/pkinit/certs/CertificateChainFactory.java
URL: http://svn.apache.org/viewvc/directory/sandbox/erodriguez/kerberos-pkinit/src/main/java/org/apache/directory/server/kerberos/pkinit/certs/CertificateChainFactory.java?rev=580663&view=auto
==============================================================================
--- directory/sandbox/erodriguez/kerberos-pkinit/src/main/java/org/apache/directory/server/kerberos/pkinit/certs/CertificateChainFactory.java (added)
+++ directory/sandbox/erodriguez/kerberos-pkinit/src/main/java/org/apache/directory/server/kerberos/pkinit/certs/CertificateChainFactory.java Sat Sep 29 18:24:45 2007
@@ -0,0 +1,298 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.server.kerberos.pkinit.certs;
+
+
+import java.security.KeyFactory;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.SecureRandom;
+import java.security.cert.X509Certificate;
+import java.security.spec.InvalidKeySpecException;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * Factory for dynamically generating certificate chains.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class CertificateChainFactory
+{
+    /** The logger for this class. */
+    private static final Logger logger = LoggerFactory.getLogger( CertificateChainFactory.class );
+
+    private static int TRUST_ANCHOR_LEVEL = 2;
+
+    private static int INTERMEDIATE_LEVEL = 1;
+
+    private static int END_ENTITY_LEVEL = 0;
+
+    private static SecureRandom secureRandom = new SecureRandom();
+
+    private static String container = "C=US, ST=Maryland, L=Forest Hill, O=Apache Software Foundation, OU=Apache Directory, CN=";
+
+    private static boolean isGenerated = false;
+
+    private static boolean isInitialized = false;
+
+    private static X509Certificate[] clientChain;
+
+    private static X509Certificate[] kdcChain;
+
+    private static PrivateKey clientPrivateKey;
+
+    private static PrivateKey kdcPrivateKey;
+
+
+    public static X509Certificate[] getKdcChain() throws Exception
+    {
+        init();
+
+        return kdcChain;
+    }
+
+
+    public static X509Certificate[] getClientChain() throws Exception
+    {
+        init();
+
+        return clientChain;
+    }
+
+
+    public static PrivateKey getKdcPrivateKey() throws Exception
+    {
+        init();
+
+        return kdcPrivateKey;
+    }
+
+
+    public static PrivateKey getClientPrivateKey() throws Exception
+    {
+        init();
+
+        return clientPrivateKey;
+    }
+
+
+    private static void init() throws Exception
+    {
+        if ( !isInitialized )
+        {
+            initClientChain();
+            initKdcChain();
+            isInitialized = true;
+        }
+    }
+
+
+    private static void initClientChain() throws Exception
+    {
+        // Make trust anchor.
+        String friendlyName = "Test Root CA";
+        String dn = container + friendlyName;
+        int validityDays = 730;
+
+        KeyPair keyPair = getKeyPair( TRUST_ANCHOR_LEVEL );
+        PrivateKey trustAnchorPrivateKey = keyPair.getPrivate();
+        PublicKey trustAnchorPublicKey = keyPair.getPublic();
+
+        X509Certificate trustAnchorCert = TrustAnchorGenerator.generate( trustAnchorPublicKey, trustAnchorPrivateKey,
+            dn, validityDays, friendlyName );
+
+        trustAnchorCert.checkValidity();
+        trustAnchorCert.verify( trustAnchorPublicKey );
+
+        logger.debug( "Generated cert for friendly name '{}', valid for {} days.", friendlyName, validityDays );
+
+        // Make intermediate client CA.
+        friendlyName = "Client Test CA 1";
+        dn = container + friendlyName;
+        validityDays = 365;
+
+        keyPair = getKeyPair( INTERMEDIATE_LEVEL );
+        PrivateKey clientCaPrivateKey = keyPair.getPrivate();
+        PublicKey clientCaPublicKey = keyPair.getPublic();
+
+        X509Certificate clientCaCert = IntermediateCaGenerator.generate( trustAnchorCert, trustAnchorPrivateKey,
+            clientCaPublicKey, dn, validityDays, friendlyName );
+
+        clientCaCert.checkValidity();
+        clientCaCert.verify( trustAnchorPublicKey );
+
+        logger.debug( "Generated cert for friendly name '{}', valid for {} days.", friendlyName, validityDays );
+
+        // Make client certificate.
+        friendlyName = "hnelson@EXAMPLE.COM UPN";
+        dn = container + friendlyName;
+        validityDays = 30;
+
+        keyPair = getKeyPair( END_ENTITY_LEVEL );
+        clientPrivateKey = keyPair.getPrivate();
+        PublicKey clientPublicKey = keyPair.getPublic();
+
+        X509Certificate clientCert = EndEntityGenerator.generate( clientCaCert, clientCaPrivateKey, clientPublicKey,
+            dn, validityDays, friendlyName );
+
+        clientCert.checkValidity();
+        clientCert.verify( clientCaPublicKey );
+
+        logger.debug( "Generated cert for friendly name '{}', valid for {} days.", friendlyName, validityDays );
+
+        // Build client chain.
+        clientChain = new X509Certificate[3];
+
+        clientChain[2] = trustAnchorCert;
+        clientChain[1] = clientCaCert;
+        clientChain[0] = clientCert;
+    }
+
+
+    private static void initKdcChain() throws Exception
+    {
+        // Make trust anchor.
+        String friendlyName = "Test Root CA";
+        String dn = container + friendlyName;
+        int validityDays = 730;
+
+        KeyPair keyPair = getKeyPair( TRUST_ANCHOR_LEVEL );
+        PrivateKey trustAnchorPrivateKey = keyPair.getPrivate();
+        PublicKey trustAnchorPublicKey = keyPair.getPublic();
+
+        X509Certificate trustAnchorCert = TrustAnchorGenerator.generate( trustAnchorPublicKey, trustAnchorPrivateKey,
+            dn, validityDays, friendlyName );
+
+        trustAnchorCert.checkValidity();
+        trustAnchorCert.verify( trustAnchorPublicKey );
+
+        logger.debug( "Generated cert for friendly name '{}', valid for {} days.", friendlyName, validityDays );
+
+        // Make intermediate KDC CA.
+        friendlyName = "KDC Test CA 1";
+        dn = container + friendlyName;
+        validityDays = 365;
+
+        keyPair = getKeyPair( INTERMEDIATE_LEVEL );
+        PrivateKey kdcCaPrivateKey = keyPair.getPrivate();
+        PublicKey kdcCaPublicKey = keyPair.getPublic();
+
+        X509Certificate kdcCaCert = IntermediateCaGenerator.generate( trustAnchorCert, trustAnchorPrivateKey,
+            kdcCaPublicKey, dn, validityDays, friendlyName );
+
+        kdcCaCert.checkValidity();
+        kdcCaCert.verify( trustAnchorPublicKey );
+
+        logger.debug( "Generated cert for friendly name '{}', valid for {} days.", friendlyName, validityDays );
+
+        // Make KDC certificate.
+        friendlyName = "krbtgt/EXAMPLE.COM@EXAMPLE.COM KDC";
+        dn = container + friendlyName;
+        validityDays = 30;
+
+        keyPair = getKeyPair( END_ENTITY_LEVEL );
+        kdcPrivateKey = keyPair.getPrivate();
+        PublicKey kdcPublicKey = keyPair.getPublic();
+
+        X509Certificate kdcCert = EndEntityGenerator.generate( kdcCaCert, kdcCaPrivateKey, kdcPublicKey, dn,
+            validityDays, friendlyName );
+
+        kdcCert.checkValidity();
+        kdcCert.verify( kdcCaPublicKey );
+
+        logger.debug( "Generated cert for friendly name '{}', valid for {} days.", friendlyName, validityDays );
+
+        // Build KDC chain.
+        kdcChain = new X509Certificate[3];
+
+        kdcChain[2] = trustAnchorCert;
+        kdcChain[1] = kdcCaCert;
+        kdcChain[0] = kdcCert;
+    }
+
+
+    /**
+     * Get a key pair for the new certificate.  Depending on the static constant
+     * 'isGenerated', these key pairs can be dynamically generated (slower) or
+     * built from static constant values (faster).
+     *
+     * @param level
+     * @return The key pair.
+     * @throws NoSuchAlgorithmException
+     * @throws NoSuchProviderException
+     * @throws InvalidKeySpecException
+     */
+    private static KeyPair getKeyPair( int level ) throws NoSuchAlgorithmException, NoSuchProviderException,
+        InvalidKeySpecException
+    {
+        if ( isGenerated )
+        {
+            KeyPairGenerator keyGen = KeyPairGenerator.getInstance( "RSA" );
+            keyGen.initialize( 1024, secureRandom );
+            return keyGen.generateKeyPair();
+        }
+        else
+        {
+            return getStaticKeyPair( level );
+        }
+    }
+
+
+    /**
+     * Get a key pair generated using static key values.  This is much faster than
+     * dynamically generating key values.
+     *
+     * @param level
+     * @return The static key pair.
+     * @throws NoSuchAlgorithmException
+     * @throws NoSuchProviderException
+     * @throws InvalidKeySpecException
+     */
+    private static KeyPair getStaticKeyPair( int level ) throws NoSuchAlgorithmException, NoSuchProviderException,
+        InvalidKeySpecException
+    {
+        KeyFactory keyFactory = KeyFactory.getInstance( "RSA", "BC" );
+
+        switch ( level )
+        {
+            case 2:
+                PrivateKey caPrivKey = keyFactory.generatePrivate( KeyPairSpec.caPrivKeySpec );
+                PublicKey caPubKey = keyFactory.generatePublic( KeyPairSpec.caPubKeySpec );
+                return new KeyPair( caPubKey, caPrivKey );
+            case 1:
+                PrivateKey intPrivKey = keyFactory.generatePrivate( KeyPairSpec.intPrivKeySpec );
+                PublicKey intPubKey = keyFactory.generatePublic( KeyPairSpec.intPubKeySpec );
+                return new KeyPair( intPubKey, intPrivKey );
+            case 0:
+            default:
+                PrivateKey privKey = keyFactory.generatePrivate( KeyPairSpec.privKeySpec );
+                PublicKey pubKey = keyFactory.generatePublic( KeyPairSpec.pubKeySpec );
+                return new KeyPair( pubKey, privKey );
+        }
+    }
+}

Propchange: directory/sandbox/erodriguez/kerberos-pkinit/src/main/java/org/apache/directory/server/kerberos/pkinit/certs/CertificateChainFactory.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: directory/sandbox/erodriguez/kerberos-pkinit/src/main/java/org/apache/directory/server/kerberos/pkinit/certs/EndEntityGenerator.java
URL: http://svn.apache.org/viewvc/directory/sandbox/erodriguez/kerberos-pkinit/src/main/java/org/apache/directory/server/kerberos/pkinit/certs/EndEntityGenerator.java?rev=580663&view=auto
==============================================================================
--- directory/sandbox/erodriguez/kerberos-pkinit/src/main/java/org/apache/directory/server/kerberos/pkinit/certs/EndEntityGenerator.java (added)
+++ directory/sandbox/erodriguez/kerberos-pkinit/src/main/java/org/apache/directory/server/kerberos/pkinit/certs/EndEntityGenerator.java Sat Sep 29 18:24:45 2007
@@ -0,0 +1,257 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.server.kerberos.pkinit.certs;
+
+
+import java.math.BigInteger;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.SignatureException;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.Calendar;
+import java.util.Date;
+
+import org.apache.directory.server.kerberos.pkinit.io.Krb5PrincipalName;
+import org.bouncycastle.asn1.ASN1EncodableVector;
+import org.bouncycastle.asn1.DERBMPString;
+import org.bouncycastle.asn1.DERObjectIdentifier;
+import org.bouncycastle.asn1.DERSequence;
+import org.bouncycastle.asn1.DERTaggedObject;
+import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
+import org.bouncycastle.asn1.x509.BasicConstraints;
+import org.bouncycastle.asn1.x509.GeneralName;
+import org.bouncycastle.asn1.x509.GeneralNames;
+import org.bouncycastle.asn1.x509.KeyPurposeId;
+import org.bouncycastle.asn1.x509.KeyUsage;
+import org.bouncycastle.asn1.x509.X509Extensions;
+import org.bouncycastle.crypto.DataLengthException;
+import org.bouncycastle.jce.PrincipalUtil;
+import org.bouncycastle.jce.X509Principal;
+import org.bouncycastle.jce.interfaces.PKCS12BagAttributeCarrier;
+import org.bouncycastle.x509.X509V3CertificateGenerator;
+import org.bouncycastle.x509.extension.AuthorityKeyIdentifierStructure;
+import org.bouncycastle.x509.extension.SubjectKeyIdentifierStructure;
+
+
+/**
+ * Generates an X.509 "end entity" certificate programmatically.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class EndEntityGenerator
+{
+    /**
+     * id-pkinit-san OBJECT IDENTIFIER ::=
+     *     { iso(1) org(3) dod(6) internet(1) security(5) kerberosv5(2) x509SanAN (2) }
+     */
+    private static final DERObjectIdentifier ID_PKINIT_SAN = new DERObjectIdentifier( "1.3.6.1.5.2.2" );
+
+    /**
+     * id-pkinit-KPClientAuth OBJECT IDENTIFIER ::=
+     * { iso(1) org(3) dod(6) internet(1) security(5) kerberosv5(2) pkinit(3) keyPurposeClientAuth(4) }
+     *     -- PKINIT client authentication.
+     *     -- Key usage bits that MUST be consistent:
+     *     -- digitalSignature.
+     */
+    private static final DERObjectIdentifier ID_PKINIT_KPCLIENTAUTH = new DERObjectIdentifier( "1.3.6.1.5.2.3.4" );
+
+    /**
+     * id-pkinit-KPKdc OBJECT IDENTIFIER ::=
+     *     { iso(1) org(3) dod(6) internet(1) security(5) kerberosv5(2) pkinit(3) keyPurposeKdc(5) }
+     *     -- Signing KDC responses.
+     *     -- Key usage bits that MUST be consistent:
+     *     -- digitalSignature.
+     */
+    private static final DERObjectIdentifier ID_PKINIT_KPKDC = new DERObjectIdentifier( "1.3.6.1.5.2.3.5" );
+
+    private static final DERObjectIdentifier ID_MS_KP_SC_LOGON = new DERObjectIdentifier( "1.3.6.1.4.1.311.20.2.2" );
+
+    private static final DERObjectIdentifier ID_MS_SAN_SC_LOGON_UPN = new DERObjectIdentifier( "1.3.6.1.4.1.311.20.2.3" );
+
+
+    /**
+     * Generate certificate.
+     * 
+     * @param issuerCert 
+     * @param issuerPrivateKey 
+     * @param publicKey 
+     * @param dn
+     * @param validityDays
+     * @param friendlyName
+     * @return The certificate.
+     * @throws InvalidKeyException
+     * @throws SecurityException
+     * @throws SignatureException
+     * @throws NoSuchAlgorithmException
+     * @throws DataLengthException
+     * @throws CertificateException
+     */
+    public static X509Certificate generate( X509Certificate issuerCert, PrivateKey issuerPrivateKey,
+        PublicKey publicKey, String dn, int validityDays, String friendlyName ) throws InvalidKeyException,
+        SecurityException, SignatureException, NoSuchAlgorithmException, DataLengthException, CertificateException
+    {
+        X509V3CertificateGenerator certGen = new X509V3CertificateGenerator();
+
+        // Set certificate attributes.
+        certGen.setSerialNumber( BigInteger.valueOf( System.currentTimeMillis() ) );
+
+        certGen.setIssuerDN( PrincipalUtil.getSubjectX509Principal( issuerCert ) );
+        certGen.setSubjectDN( new X509Principal( dn ) );
+
+        certGen.setNotBefore( new Date() );
+
+        Calendar expiry = Calendar.getInstance();
+        expiry.add( Calendar.DAY_OF_YEAR, validityDays );
+
+        certGen.setNotAfter( expiry.getTime() );
+
+        certGen.setPublicKey( publicKey );
+        certGen.setSignatureAlgorithm( "SHA1WithRSAEncryption" );
+
+        certGen
+            .addExtension( X509Extensions.SubjectKeyIdentifier, false, new SubjectKeyIdentifierStructure( publicKey ) );
+
+        // MAY set BasicConstraints=false or not at all.
+        certGen.addExtension( X509Extensions.BasicConstraints, true, new BasicConstraints( false ) );
+
+        certGen.addExtension( X509Extensions.AuthorityKeyIdentifier, false, new AuthorityKeyIdentifierStructure(
+            issuerCert ) );
+
+        certGen.addExtension( X509Extensions.KeyUsage, true, new KeyUsage( KeyUsage.digitalSignature
+            | KeyUsage.keyEncipherment | KeyUsage.dataEncipherment ) );
+
+        ASN1EncodableVector keyPurposeVector = new ASN1EncodableVector();
+        keyPurposeVector.add( KeyPurposeId.id_kp_smartcardlogon );
+        //keyPurposeVector.add( KeyPurposeId.id_kp_serverAuth );
+        DERSequence keyPurposeOids = new DERSequence( keyPurposeVector );
+
+        // If critical, will throw unsupported EKU.
+        certGen.addExtension( X509Extensions.ExtendedKeyUsage, false, keyPurposeOids );
+
+        Krb5PrincipalName principalName = new Krb5PrincipalName();
+        ASN1EncodableVector pkinitSanVector = new ASN1EncodableVector();
+        pkinitSanVector.add( ID_PKINIT_SAN );
+        pkinitSanVector.add( new DERTaggedObject( 0, principalName.getSequence() ) );
+        DERSequence pkinitSan = new DERSequence( pkinitSanVector );
+
+        String dnsName = "localhost";
+
+        ASN1EncodableVector sanVector = new ASN1EncodableVector();
+        sanVector.add( new GeneralName( GeneralName.otherName, pkinitSan ) );
+        sanVector.add( new GeneralName( GeneralName.dNSName, dnsName ) );
+        DERSequence san = new DERSequence( sanVector );
+
+        GeneralNames sanGeneralNames = new GeneralNames( san );
+
+        certGen.addExtension( X509Extensions.SubjectAlternativeName, true, sanGeneralNames );
+
+        /*
+         * The KDC MAY require the presence of an Extended Key Usage (EKU) KeyPurposeId
+         * [RFC3280] id-pkinit-KPClientAuth in the extensions field of the client's
+         * X.509 certificate.
+         */
+
+        /*
+         * The digitalSignature key usage bit [RFC3280] MUST be asserted when the
+         * intended purpose of the client's X.509 certificate is restricted with
+         * the id-pkinit-KPClientAuth EKU.
+         */
+
+        /*
+         * KDCs implementing this requirement SHOULD also accept the EKU KeyPurposeId
+         * id-ms-kp-sc-logon (1.3.6.1.4.1.311.20.2.2) as meeting the requirement, as
+         * there are a large number of X.509 client certificates deployed for use
+         * with PKINIT that have this EKU.
+         */
+
+        // KDC
+        /*
+         * In addition, unless the client can otherwise verify that the public key
+         * used to verify the KDC's signature is bound to the KDC of the target realm,
+         * the KDC's X.509 certificate MUST contain a Subject Alternative Name extension
+         * [RFC3280] carrying an AnotherName whose type-id is id-pkinit-san (as defined
+         * in Section 3.2.2) and whose value is a KRB5PrincipalName that matches the
+         * name of the TGS of the target realm (as defined in Section 7.3 of [RFC4120]).
+         */
+
+        /*
+         * Unless the client knows by some other means that the KDC certificate is
+         * intended for a Kerberos KDC, the client MUST require that the KDC certificate
+         * contains the EKU KeyPurposeId [RFC3280] id-pkinit-KPKdc.
+         */
+
+        /*
+         * The digitalSignature key usage bit [RFC3280] MUST be asserted when the
+         * intended purpose of the KDC's X.509 certificate is restricted with the
+         * id-pkinit-KPKdc EKU.
+         */
+
+        /*
+         * If the KDC certificate contains the Kerberos TGS name encoded as an id-pkinit-san
+         * SAN, this certificate is certified by the issuing CA as a KDC certificate,
+         * therefore the id-pkinit-KPKdc EKU is not required.
+         */
+
+        /*
+         * KDC certificates issued by Windows 2000 Enterprise CAs contain a dNSName
+         * SAN with the DNS name of the host running the KDC, and the id-kp-serverAuth
+         * EKU [RFC3280].
+         */
+
+        /*
+         * KDC certificates issued by Windows 2003 Enterprise CAs contain a dNSName
+         * SAN with the DNS name of the host running the KDC, the id-kp-serverAuth
+         * EKU, and the id-ms-kp-sc-logon EKU.
+         */
+
+        /*
+         * RFC: KDC certificates with id-pkinit-san SAN as specified in this RFC.
+         * 
+         * MS:  dNSName SAN containing the domain name of the KDC
+         *      id-pkinit-KPKdc EKU
+         *      id-kp-serverAuth EKU.
+         */
+
+        /*
+         * Client certificates accepted by Windows 2000 and Windows 2003 Server KDCs
+         * must contain an id-ms-san-sc-logon-upn (1.3.6.1.4.1.311.20.2.3) SAN and
+         * the id-ms-kp-sc-logon EKU.  The id-ms-san-sc-logon-upn SAN contains a
+         * UTF8-encoded string whose value is that of the Directory Service attribute
+         * UserPrincipalName of the client account object, and the purpose of including
+         * the id-ms-san-sc-logon-upn SAN in the client certificate is to validate
+         * the client mapping (in other words, the client's public key is bound to
+         * the account that has this UserPrincipalName value).
+         */
+
+        X509Certificate cert = certGen.generate( issuerPrivateKey );
+
+        PKCS12BagAttributeCarrier bagAttr = ( PKCS12BagAttributeCarrier ) cert;
+
+        bagAttr.setBagAttribute( PKCSObjectIdentifiers.pkcs_9_at_friendlyName, new DERBMPString( friendlyName ) );
+        bagAttr.setBagAttribute( PKCSObjectIdentifiers.pkcs_9_at_localKeyId, new SubjectKeyIdentifierStructure(
+            publicKey ) );
+
+        return cert;
+    }
+}

Propchange: directory/sandbox/erodriguez/kerberos-pkinit/src/main/java/org/apache/directory/server/kerberos/pkinit/certs/EndEntityGenerator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: directory/sandbox/erodriguez/kerberos-pkinit/src/main/java/org/apache/directory/server/kerberos/pkinit/certs/IntermediateCaGenerator.java
URL: http://svn.apache.org/viewvc/directory/sandbox/erodriguez/kerberos-pkinit/src/main/java/org/apache/directory/server/kerberos/pkinit/certs/IntermediateCaGenerator.java?rev=580663&view=auto
==============================================================================
--- directory/sandbox/erodriguez/kerberos-pkinit/src/main/java/org/apache/directory/server/kerberos/pkinit/certs/IntermediateCaGenerator.java (added)
+++ directory/sandbox/erodriguez/kerberos-pkinit/src/main/java/org/apache/directory/server/kerberos/pkinit/certs/IntermediateCaGenerator.java Sat Sep 29 18:24:45 2007
@@ -0,0 +1,116 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.server.kerberos.pkinit.certs;
+
+
+import java.math.BigInteger;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.SignatureException;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.Calendar;
+import java.util.Date;
+
+import org.bouncycastle.asn1.DERBMPString;
+import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
+import org.bouncycastle.asn1.x509.BasicConstraints;
+import org.bouncycastle.asn1.x509.KeyUsage;
+import org.bouncycastle.asn1.x509.X509Extensions;
+import org.bouncycastle.crypto.DataLengthException;
+import org.bouncycastle.jce.PrincipalUtil;
+import org.bouncycastle.jce.X509Principal;
+import org.bouncycastle.jce.interfaces.PKCS12BagAttributeCarrier;
+import org.bouncycastle.x509.X509V3CertificateGenerator;
+import org.bouncycastle.x509.extension.AuthorityKeyIdentifierStructure;
+import org.bouncycastle.x509.extension.SubjectKeyIdentifierStructure;
+
+
+/**
+ * Generates an X.509 "intermediate CA" certificate programmatically.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class IntermediateCaGenerator
+{
+    /**
+     * Create certificate.
+     * 
+     * @param issuerCert 
+     * @param issuerPrivateKey 
+     * @param publicKey 
+     * @param dn
+     * @param validityDays
+     * @param friendlyName
+     * @return The certificate.
+     * @throws InvalidKeyException
+     * @throws SecurityException
+     * @throws SignatureException
+     * @throws NoSuchAlgorithmException
+     * @throws DataLengthException
+     * @throws CertificateException
+     */
+    public static X509Certificate generate( X509Certificate issuerCert, PrivateKey issuerPrivateKey,
+        PublicKey publicKey, String dn, int validityDays, String friendlyName ) throws InvalidKeyException,
+        SecurityException, SignatureException, NoSuchAlgorithmException, DataLengthException, CertificateException
+    {
+        X509V3CertificateGenerator certGen = new X509V3CertificateGenerator();
+
+        // Set certificate attributes.
+        certGen.setSerialNumber( BigInteger.valueOf( System.currentTimeMillis() ) );
+
+        certGen.setIssuerDN( PrincipalUtil.getSubjectX509Principal( issuerCert ) );
+        certGen.setSubjectDN( new X509Principal( dn ) );
+
+        certGen.setNotBefore( new Date() );
+
+        Calendar expiry = Calendar.getInstance();
+        expiry.add( Calendar.DAY_OF_YEAR, validityDays );
+
+        certGen.setNotAfter( expiry.getTime() );
+
+        certGen.setPublicKey( publicKey );
+        certGen.setSignatureAlgorithm( "SHA1WithRSAEncryption" );
+
+        certGen
+            .addExtension( X509Extensions.SubjectKeyIdentifier, false, new SubjectKeyIdentifierStructure( publicKey ) );
+
+        certGen.addExtension( X509Extensions.BasicConstraints, true, new BasicConstraints( 0 ) );
+
+        certGen.addExtension( X509Extensions.AuthorityKeyIdentifier, false, new AuthorityKeyIdentifierStructure(
+            issuerCert ) );
+
+        certGen.addExtension( X509Extensions.KeyUsage, true, new KeyUsage( KeyUsage.digitalSignature
+            | KeyUsage.keyCertSign | KeyUsage.cRLSign ) );
+
+        X509Certificate cert = certGen.generate( issuerPrivateKey );
+
+        PKCS12BagAttributeCarrier bagAttr = ( PKCS12BagAttributeCarrier ) cert;
+
+        bagAttr.setBagAttribute( PKCSObjectIdentifiers.pkcs_9_at_friendlyName, new DERBMPString( friendlyName ) );
+        bagAttr.setBagAttribute( PKCSObjectIdentifiers.pkcs_9_at_localKeyId, new SubjectKeyIdentifierStructure(
+            publicKey ) );
+
+        return cert;
+    }
+}

Propchange: directory/sandbox/erodriguez/kerberos-pkinit/src/main/java/org/apache/directory/server/kerberos/pkinit/certs/IntermediateCaGenerator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: directory/sandbox/erodriguez/kerberos-pkinit/src/main/java/org/apache/directory/server/kerberos/pkinit/certs/KeyPairSpec.java
URL: http://svn.apache.org/viewvc/directory/sandbox/erodriguez/kerberos-pkinit/src/main/java/org/apache/directory/server/kerberos/pkinit/certs/KeyPairSpec.java?rev=580663&view=auto
==============================================================================
--- directory/sandbox/erodriguez/kerberos-pkinit/src/main/java/org/apache/directory/server/kerberos/pkinit/certs/KeyPairSpec.java (added)
+++ directory/sandbox/erodriguez/kerberos-pkinit/src/main/java/org/apache/directory/server/kerberos/pkinit/certs/KeyPairSpec.java Sat Sep 29 18:24:45 2007
@@ -0,0 +1,114 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.server.kerberos.pkinit.certs;
+
+
+import java.math.BigInteger;
+import java.security.spec.RSAPrivateCrtKeySpec;
+import java.security.spec.RSAPublicKeySpec;
+
+
+/**
+ * Specifications for asymmetric key pairs.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+class KeyPairSpec
+{
+    // End-entity keys.
+    static RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec(
+        new BigInteger(
+            "b4a7e46170574f16a97082b22be58b6a2a629798419be12872a4bdba626cfae9900f76abfb12139dce5de56564fab2b6543165a040c606887420e33d91ed7ed7",
+            16 ), new BigInteger( "11", 16 ) );
+
+    static RSAPrivateCrtKeySpec privKeySpec = new RSAPrivateCrtKeySpec(
+        new BigInteger(
+            "b4a7e46170574f16a97082b22be58b6a2a629798419be12872a4bdba626cfae9900f76abfb12139dce5de56564fab2b6543165a040c606887420e33d91ed7ed7",
+            16 ),
+        new BigInteger( "11", 16 ),
+        new BigInteger(
+            "9f66f6b05410cd503b2709e88115d55daced94d1a34d4e32bf824d0dde6028ae79c5f07b580f5dce240d7111f7ddb130a7945cd7d957d1920994da389f490c89",
+            16 ), new BigInteger( "c0a0758cdf14256f78d4708c86becdead1b50ad4ad6c5c703e2168fbf37884cb", 16 ),
+        new BigInteger( "f01734d7960ea60070f1b06f2bb81bfac48ff192ae18451d5e56c734a5aab8a5", 16 ), new BigInteger(
+            "b54bb9edff22051d9ee60f9351a48591b6500a319429c069a3e335a1d6171391", 16 ), new BigInteger(
+            "d3d83daf2a0cecd3367ae6f8ae1aeb82e9ac2f816c6fc483533d8297dd7884cd", 16 ), new BigInteger(
+            "b8f52fc6f38593dabb661d3f50f8897f8106eee68b1bce78a95b132b4e5b5d19", 16 ) );
+
+    // Intermediate keys.
+    static RSAPublicKeySpec intPubKeySpec = new RSAPublicKeySpec(
+        new BigInteger(
+            "8de0d113c5e736969c8d2b047a243f8fe18edad64cde9e842d3669230ca486f7cfdde1f8eec54d1905fff04acc85e61093e180cadc6cea407f193d44bb0e9449b8dbb49784cd9e36260c39e06a947299978c6ed8300724e887198cfede20f3fbde658fa2bd078be946a392bd349f2b49c486e20c405588e306706c9017308e69",
+            16 ), new BigInteger( "ffff", 16 ) );
+
+    static RSAPrivateCrtKeySpec intPrivKeySpec = new RSAPrivateCrtKeySpec(
+        new BigInteger(
+            "8de0d113c5e736969c8d2b047a243f8fe18edad64cde9e842d3669230ca486f7cfdde1f8eec54d1905fff04acc85e61093e180cadc6cea407f193d44bb0e9449b8dbb49784cd9e36260c39e06a947299978c6ed8300724e887198cfede20f3fbde658fa2bd078be946a392bd349f2b49c486e20c405588e306706c9017308e69",
+            16 ),
+        new BigInteger( "ffff", 16 ),
+        new BigInteger(
+            "7deb1b194a85bcfd29cf871411468adbc987650903e3bacc8338c449ca7b32efd39ffc33bc84412fcd7df18d23ce9d7c25ea910b1ae9985373e0273b4dca7f2e0db3b7314056ac67fd277f8f89cf2fd73c34c6ca69f9ba477143d2b0e2445548aa0b4a8473095182631da46844c356f5e5c7522eb54b5a33f11d730ead9c0cff",
+            16 ),
+        new BigInteger(
+            "ef4cede573cea47f83699b814de4302edb60eefe426c52e17bd7870ec7c6b7a24fe55282ebb73775f369157726fcfb988def2b40350bdca9e5b418340288f649",
+            16 ),
+        new BigInteger(
+            "97c7737d1b9a0088c3c7b528539247fd2a1593e7e01cef18848755be82f4a45aa093276cb0cbf118cb41117540a78f3fc471ba5d69f0042274defc9161265721",
+            16 ),
+        new BigInteger(
+            "6c641094e24d172728b8da3c2777e69adfd0839085be7e38c7c4a2dd00b1ae969f2ec9d23e7e37090fcd449a40af0ed463fe1c612d6810d6b4f58b7bfa31eb5f",
+            16 ),
+        new BigInteger(
+            "70b7123e8e69dfa76feb1236d0a686144b00e9232ed52b73847e74ef3af71fb45ccb24261f40d27f98101e230cf27b977a5d5f1f15f6cf48d5cb1da2a3a3b87f",
+            16 ),
+        new BigInteger(
+            "e38f5750d97e270996a286df2e653fd26c242106436f5bab0f4c7a9e654ce02665d5a281f2c412456f2d1fa26586ef04a9adac9004ca7f913162cb28e13bf40d",
+            16 ) );
+
+    // Trust anchor keys.
+    static RSAPublicKeySpec caPubKeySpec = new RSAPublicKeySpec(
+        new BigInteger(
+            "b259d2d6e627a768c94be36164c2d9fc79d97aab9253140e5bf17751197731d6f7540d2509e7b9ffee0a70a6e26d56e92d2edd7f85aba85600b69089f35f6bdbf3c298e05842535d9f064e6b0391cb7d306e0a2d20c4dfb4e7b49a9640bdea26c10ad69c3f05007ce2513cee44cfe01998e62b6c3637d3fc0391079b26ee36d5",
+            16 ), new BigInteger( "11", 16 ) );
+
+    static RSAPrivateCrtKeySpec caPrivKeySpec = new RSAPrivateCrtKeySpec(
+        new BigInteger(
+            "b259d2d6e627a768c94be36164c2d9fc79d97aab9253140e5bf17751197731d6f7540d2509e7b9ffee0a70a6e26d56e92d2edd7f85aba85600b69089f35f6bdbf3c298e05842535d9f064e6b0391cb7d306e0a2d20c4dfb4e7b49a9640bdea26c10ad69c3f05007ce2513cee44cfe01998e62b6c3637d3fc0391079b26ee36d5",
+            16 ),
+        new BigInteger( "11", 16 ),
+        new BigInteger(
+            "92e08f83cc9920746989ca5034dcb384a094fb9c5a6288fcc4304424ab8f56388f72652d8fafc65a4b9020896f2cde297080f2a540e7b7ce5af0b3446e1258d1dd7f245cf54124b4c6e17da21b90a0ebd22605e6f45c9f136d7a13eaac1c0f7487de8bd6d924972408ebb58af71e76fd7b012a8d0e165f3ae2e5077a8648e619",
+            16 ),
+        new BigInteger(
+            "f75e80839b9b9379f1cf1128f321639757dba514642c206bbbd99f9a4846208b3e93fbbe5e0527cc59b1d4b929d9555853004c7c8b30ee6a213c3d1bb7415d03",
+            16 ),
+        new BigInteger(
+            "b892d9ebdbfc37e397256dd8a5d3123534d1f03726284743ddc6be3a709edb696fc40c7d902ed804c6eee730eee3d5b20bf6bd8d87a296813c87d3b3cc9d7947",
+            16 ),
+        new BigInteger(
+            "1d1a2d3ca8e52068b3094d501c9a842fec37f54db16e9a67070a8b3f53cc03d4257ad252a1a640eadd603724d7bf3737914b544ae332eedf4f34436cac25ceb5",
+            16 ),
+        new BigInteger(
+            "6c929e4e81672fef49d9c825163fec97c4b7ba7acb26c0824638ac22605d7201c94625770984f78a56e6e25904fe7db407099cad9b14588841b94f5ab498dded",
+            16 ),
+        new BigInteger(
+            "dae7651ee69ad1d081ec5e7188ae126f6004ff39556bde90e0b870962fa7b926d070686d8244fe5a9aa709a95686a104614834b0ada4b10f53197a5cb4c97339",
+            16 ) );
+}

Propchange: directory/sandbox/erodriguez/kerberos-pkinit/src/main/java/org/apache/directory/server/kerberos/pkinit/certs/KeyPairSpec.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: directory/sandbox/erodriguez/kerberos-pkinit/src/main/java/org/apache/directory/server/kerberos/pkinit/certs/TrustAnchorGenerator.java
URL: http://svn.apache.org/viewvc/directory/sandbox/erodriguez/kerberos-pkinit/src/main/java/org/apache/directory/server/kerberos/pkinit/certs/TrustAnchorGenerator.java?rev=580663&view=auto
==============================================================================
--- directory/sandbox/erodriguez/kerberos-pkinit/src/main/java/org/apache/directory/server/kerberos/pkinit/certs/TrustAnchorGenerator.java (added)
+++ directory/sandbox/erodriguez/kerberos-pkinit/src/main/java/org/apache/directory/server/kerberos/pkinit/certs/TrustAnchorGenerator.java Sat Sep 29 18:24:45 2007
@@ -0,0 +1,111 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.server.kerberos.pkinit.certs;
+
+
+import java.math.BigInteger;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.SignatureException;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.Calendar;
+import java.util.Date;
+
+import org.bouncycastle.asn1.DERBMPString;
+import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
+import org.bouncycastle.asn1.x509.BasicConstraints;
+import org.bouncycastle.asn1.x509.KeyUsage;
+import org.bouncycastle.asn1.x509.X509Extensions;
+import org.bouncycastle.crypto.DataLengthException;
+import org.bouncycastle.jce.X509Principal;
+import org.bouncycastle.jce.interfaces.PKCS12BagAttributeCarrier;
+import org.bouncycastle.x509.X509V3CertificateGenerator;
+import org.bouncycastle.x509.extension.SubjectKeyIdentifierStructure;
+
+
+/**
+ * Generates an X.509 "trust anchor" certificate programmatically.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class TrustAnchorGenerator
+{
+    /**
+     * Create CA certificate.
+     * 
+     * @param publicKey 
+     * @param privateKey 
+     * @param dn
+     * @param validityDays
+     * @param friendlyName
+     * @return The certificate.
+     * @throws InvalidKeyException
+     * @throws SecurityException
+     * @throws SignatureException
+     * @throws NoSuchAlgorithmException
+     * @throws DataLengthException
+     * @throws CertificateException
+     */
+    public static X509Certificate generate( PublicKey publicKey, PrivateKey privateKey, String dn, int validityDays,
+        String friendlyName ) throws InvalidKeyException, SecurityException, SignatureException,
+        NoSuchAlgorithmException, DataLengthException, CertificateException
+    {
+        X509V3CertificateGenerator certGen = new X509V3CertificateGenerator();
+
+        // Set certificate attributes.
+        certGen.setSerialNumber( BigInteger.valueOf( System.currentTimeMillis() ) );
+
+        X509Principal x509Principal = new X509Principal( dn );
+        certGen.setIssuerDN( x509Principal );
+        certGen.setSubjectDN( x509Principal );
+
+        certGen.setNotBefore( new Date() );
+
+        Calendar expiry = Calendar.getInstance();
+        expiry.add( Calendar.DAY_OF_YEAR, validityDays );
+
+        certGen.setNotAfter( expiry.getTime() );
+
+        certGen.setPublicKey( publicKey );
+        certGen.setSignatureAlgorithm( "SHA1WithRSAEncryption" );
+
+        certGen
+            .addExtension( X509Extensions.SubjectKeyIdentifier, false, new SubjectKeyIdentifierStructure( publicKey ) );
+
+        certGen.addExtension( X509Extensions.BasicConstraints, true, new BasicConstraints( 1 ) );
+
+        certGen.addExtension( X509Extensions.KeyUsage, true, new KeyUsage( KeyUsage.digitalSignature
+            | KeyUsage.keyCertSign | KeyUsage.cRLSign ) );
+
+        X509Certificate cert = certGen.generate( privateKey );
+
+        PKCS12BagAttributeCarrier bagAttr = ( PKCS12BagAttributeCarrier ) cert;
+
+        bagAttr.setBagAttribute( PKCSObjectIdentifiers.pkcs_9_at_friendlyName, new DERBMPString( friendlyName ) );
+        bagAttr.setBagAttribute( PKCSObjectIdentifiers.pkcs_9_at_localKeyId, new SubjectKeyIdentifierStructure(
+            publicKey ) );
+
+        return cert;
+    }
+}

Propchange: directory/sandbox/erodriguez/kerberos-pkinit/src/main/java/org/apache/directory/server/kerberos/pkinit/certs/TrustAnchorGenerator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: directory/sandbox/erodriguez/kerberos-pkinit/src/test/java/org/apache/directory/server/kerberos/pkinit/certs/CertificateChainFactoryTest.java
URL: http://svn.apache.org/viewvc/directory/sandbox/erodriguez/kerberos-pkinit/src/test/java/org/apache/directory/server/kerberos/pkinit/certs/CertificateChainFactoryTest.java?rev=580663&view=auto
==============================================================================
--- directory/sandbox/erodriguez/kerberos-pkinit/src/test/java/org/apache/directory/server/kerberos/pkinit/certs/CertificateChainFactoryTest.java (added)
+++ directory/sandbox/erodriguez/kerberos-pkinit/src/test/java/org/apache/directory/server/kerberos/pkinit/certs/CertificateChainFactoryTest.java Sat Sep 29 18:24:45 2007
@@ -0,0 +1,119 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.server.kerberos.pkinit.certs;
+
+
+import java.security.InvalidAlgorithmParameterException;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.Security;
+import java.security.cert.CertPath;
+import java.security.cert.CertPathValidator;
+import java.security.cert.CertPathValidatorException;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.PKIXParameters;
+import java.security.cert.TrustAnchor;
+import java.security.cert.X509Certificate;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import junit.framework.TestCase;
+
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+
+
+/**
+ * Tests the dynamic generation of certificate chains.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class CertificateChainFactoryTest extends TestCase
+{
+    public void setUp()
+    {
+        if ( Security.getProvider( BouncyCastleProvider.PROVIDER_NAME ) == null )
+        {
+            Security.addProvider( new BouncyCastleProvider() );
+        }
+    }
+
+
+    /**
+     * Tests construction of the client chain.
+     * 
+     * The created certificates can be displayed with a command like:
+     * 
+     * openssl pkcs12 -nodes -info -in /tmp/test.p12 > /tmp/test.cert && openssl x509 -noout -text -in /tmp/test.cert
+     * 
+     * @throws Exception 
+     */
+    public void testClientChain() throws Exception
+    {
+        X509Certificate[] clientChain = CertificateChainFactory.getClientChain();
+
+        validateChain( clientChain );
+    }
+
+
+    /**
+     * Tests construction of the KDC chain.
+     * 
+     * The created certificates can be displayed with a command like:
+     * 
+     * openssl pkcs12 -nodes -info -in /tmp/test.p12 > /tmp/test.cert && openssl x509 -noout -text -in /tmp/test.cert
+     * 
+     * @throws Exception 
+     */
+    public void testKdcChain() throws Exception
+    {
+        X509Certificate[] kdcChain = CertificateChainFactory.getKdcChain();
+
+        validateChain( kdcChain );
+    }
+
+
+    /**
+     * Validates a chain of {@link X509Certificate}s.
+     *
+     * @param chain
+     * @throws CertificateException
+     * @throws InvalidAlgorithmParameterException
+     */
+    private void validateChain( X509Certificate[] chain ) throws CertificateException,
+        InvalidAlgorithmParameterException, NoSuchAlgorithmException, NoSuchProviderException,
+        InvalidAlgorithmParameterException, CertPathValidatorException
+    {
+        List<X509Certificate> certificateList = Arrays.asList( chain );
+        CertificateFactory certificateFactory = CertificateFactory.getInstance( "X.509" );
+        CertPath certPath = certificateFactory.generateCertPath( certificateList );
+
+        CertPathValidator cpv = CertPathValidator.getInstance( "PKIX", "BC" );
+
+        TrustAnchor trustAnchor = new TrustAnchor( chain[chain.length - 1], null );
+
+        PKIXParameters parameters = new PKIXParameters( Collections.singleton( trustAnchor ) );
+        parameters.setRevocationEnabled( false );
+
+        cpv.validate( certPath, parameters );
+    }
+}

Propchange: directory/sandbox/erodriguez/kerberos-pkinit/src/test/java/org/apache/directory/server/kerberos/pkinit/certs/CertificateChainFactoryTest.java
------------------------------------------------------------------------------
    svn:eol-style = native