A little more work on the credentials loader.
authorwassa <wassa@ab3bd59b-922f-494d-bb5f-6f0a3c29deca>
Thu, 20 Nov 2003 21:50:58 +0000 (21:50 +0000)
committerwassa <wassa@ab3bd59b-922f-494d-bb5f-6f0a3c29deca>
Thu, 20 Nov 2003 21:50:58 +0000 (21:50 +0000)
git-svn-id: https://subversion.switch.ch/svn/shibboleth/java-idp/trunk@794 ab3bd59b-922f-494d-bb5f-6f0a3c29deca

data/credentials2.xml [new file with mode: 0644]
src/edu/internet2/middleware/shibboleth/common/Credentials.java
tests/conf/test.pemcrt [new file with mode: 0644]
tests/edu/internet2/middleware/shibboleth/common/CredentialsTests.java

diff --git a/data/credentials2.xml b/data/credentials2.xml
new file mode 100644 (file)
index 0000000..b58dadc
--- /dev/null
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Credentials xmlns="urn:mace:shibboleth:credentials" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" 
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
+       xsi:schemaLocation="urn:mace:shibboleth:credentials shibboleth.xsd">
+       
+       <FileCredResolver id="test">
+               <Certificate format="PEM">
+                       <Path>/conf/test.pemcrt</Path>
+               </Certificate>
+               <Key format="PEM">
+                       <Path>/conf/test.pemkey</Path>
+               </Key>
+       </FileCredResolver>
+</Credentials>
\ No newline at end of file
index e7be474..3542bef 100644 (file)
 package edu.internet2.middleware.shibboleth.common;
 
 import java.io.IOException;
+import java.io.InputStream;
+import java.security.KeyFactory;
 import java.security.KeyStore;
 import java.security.KeyStoreException;
 import java.security.NoSuchAlgorithmException;
 import java.security.PrivateKey;
 import java.security.UnrecoverableKeyException;
+import java.util.Collection;
 import java.util.Hashtable;
+import java.util.Iterator;
 
 import java.security.cert.Certificate;
 import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
 import java.security.cert.X509Certificate;
+import java.security.spec.PKCS8EncodedKeySpec;
 
 import org.apache.log4j.Logger;
 import org.w3c.dom.Element;
@@ -155,13 +161,190 @@ class KeyInfoCredentialResolver implements CredentialResolver {
 
 class FileCredentialResolver implements CredentialResolver {
        private static Logger log = Logger.getLogger(FileCredentialResolver.class.getName());
-       FileCredentialResolver() throws CredentialFactoryException {
-               log.error("Credential Resolver (FileCredentialResolver) not implemented");
-               throw new CredentialFactoryException("Failed to load credential.");
+
+       public Credential loadCredential(Element e) throws CredentialFactoryException {
+
+               if (!e.getTagName().equals("FileCredResolver")) {
+                       log.error("Invalid Credential Resolver configuration: expected <FileCredResolver> .");
+                       throw new CredentialFactoryException("Failed to initialize Credential Resolver.");
+               }
+
+               String id = e.getAttribute("id");
+               if (id == null || id.equals("")) {
+                       log.error("Credential Resolvers require specification of the attribute \"id\".");
+                       throw new CredentialFactoryException("Failed to initialize Credential Resolver.");
+               }
+
+               String certFormat = getCertFormat(e);
+               String certPath = getCertPath(e);
+               String keyFormat = "DER";
+               String keyPath = "/conf/test.pemkey";
+               log.debug("Certificate Format: (" + certFormat + ").");
+               log.debug("Certificate Path: (" + certPath + ").");
+               
+               //TODO provider optional
+               //TODO other kinds of certs?
+               try {
+               CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
+               Collection chain = certFactory.generateCertificates(new ShibResource(certPath, this.getClass()).getInputStream());
+               if (chain.isEmpty()) {
+                       log.error("File did not contain any valid certificates.");
+                       throw new CredentialFactoryException("File did not contain any valid certificates.");
+               }
+               Iterator iterator = chain.iterator();
+               while (iterator.hasNext()) {
+                       System.err.println(((X509Certificate)iterator.next()).getSubjectDN());
+               }
+               //TODO remove this
+               }catch (Exception p) {
+                       System.err.println(p);
+                       p.printStackTrace();
+               }
+               
+               try {
+                       
+                       //TODO provider??
+                       //TODO other algorithms
+                                       KeyFactory keyFactory = KeyFactory.getInstance("RSA");
+                                       InputStream keyStream = new ShibResource(certPath, this.getClass()).getInputStream();
+                                       byte[] inputBuffer = new byte[8];
+                                       int i;
+                                       ByteContainer inputBytes = new ByteContainer(400);
+                                       do {
+                                               i = keyStream.read(inputBuffer);
+                                               for (int j = 0; j < i; j++) {
+                                                       inputBytes.append(inputBuffer[j]);
+                                               }
+                                       } while (i > -1);
+
+//TODO other encodings?
+                                       PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(inputBytes.toByteArray());
+                                       PrivateKey key = keyFactory.generatePrivate(keySpec);
+
+                               } catch (Exception p) {
+                                       log.error("Problem reading private key: " + p.getMessage());
+                                       //throw new ExtKeyToolException("Problem reading private key.  Keys should be DER encoded pkcs8 or DER encoded native format.");
+                               }
+               
+
+               return new Credential(null, null);
        }
-       public Credential loadCredential(Element e) {
-               return null;
+       
+       private String getCertFormat(Element e) throws CredentialFactoryException {
+
+               NodeList certificateElements = e.getElementsByTagNameNS(Credentials.credentialsNamespace, "Certificate");
+               if (certificateElements.getLength() < 1) {
+                       log.error("Certificate not specified.");
+                       throw new CredentialFactoryException("File Credential Resolver requires a <Certificate> specification.");
+               }
+               if (certificateElements.getLength() > 1) {
+                       log.error("Multiple Certificate path specifications, using first.");
+               }
+               
+               String format = ((Element)certificateElements.item(0)).getAttribute("id");
+               if (format == null || format.equals("")) {
+                       log.debug("No format specified for certificate, using default (PEM) format.");
+                       format = "PEM";
+               }
+               
+               if ((!format.equals("PEM")) && (!format.equals("DER"))) {
+                       log.error("File credential resolver only supports the (DER) and (PEM) formats.");
+                       throw new CredentialFactoryException("Failed to initialize Credential Resolver.");
+               }
+               
+               return format;
+       }
+
+       private String getCertPath(Element e) throws CredentialFactoryException {
+
+               NodeList certificateElements = e.getElementsByTagNameNS(Credentials.credentialsNamespace, "Certificate");
+               if (certificateElements.getLength() < 1) {
+                       log.error("Certificate not specified.");
+                       throw new CredentialFactoryException("File Credential Resolver requires a <Certificate> specification.");
+               }
+               if (certificateElements.getLength() > 1) {
+                       log.error("Multiple Certificate path specifications, using first.");
+               }
+               
+               NodeList pathElements = ((Element) certificateElements.item(0)).getElementsByTagNameNS(Credentials.credentialsNamespace, "Path");
+               if (pathElements.getLength() < 1) {
+                       log.error("Certificate path not specified.");
+                       throw new CredentialFactoryException("File Credential Resolver requires a <Certificate><Path/></Certificate> specification.");
+               }
+               if (pathElements.getLength() > 1) {
+                       log.error("Multiple Certificate path specifications, using first.");
+               }
+               Node tnode = pathElements.item(0).getFirstChild();
+               String path = null;
+               if (tnode != null && tnode.getNodeType() == Node.TEXT_NODE) {
+                       path = tnode.getNodeValue();
+               }
+               if (path == null || path.equals("")) {
+                       log.error("Certificate path not specified.");
+                       throw new CredentialFactoryException("File Credential Resolver requires a <Certificate><Path/></Certificate> specification.");
+               }
+               return path;
+       }
+       
+       
+       
+       /**
+        * Auto-enlarging container for bytes.
+        */
+
+       // Sure makes you wish bytes were first class objects.
+
+       private class ByteContainer {
+
+               private byte[] buffer;
+               private int cushion;
+               private int currentSize = 0;
+
+               private ByteContainer(int cushion) {
+                       buffer = new byte[cushion];
+                       this.cushion = cushion;
+               }
+
+               private void grow() {
+                       log.debug("Growing ByteContainer.");
+                       int newSize = currentSize + cushion;
+                       byte[] b = new byte[newSize];
+                       int toCopy = Math.min(currentSize, newSize);
+                       int i;
+                       for (i = 0; i < toCopy; i++) {
+                               b[i] = buffer[i];
+                       }
+                       buffer = b;
+               }
+
+               /** 
+                * Returns an array of the bytes in the container. <p>
+                */
+
+               private byte[] toByteArray() {
+                       byte[] b = new byte[currentSize];
+                       for (int i = 0; i < currentSize; i++) {
+                               b[i] = buffer[i];
+                       }
+                       return b;
+               }
+
+               /** 
+                * Add one byte to the end of the container.
+                */
+
+               private void append(byte b) {
+                       if (currentSize == buffer.length) {
+                               grow();
+                       }
+                       buffer[currentSize] = b;
+                       currentSize++;
+               }
+
        }
+       
+       
+       
 }
 
 class KeystoreCredentialResolver implements CredentialResolver {
diff --git a/tests/conf/test.pemcrt b/tests/conf/test.pemcrt
new file mode 100644 (file)
index 0000000..cf449c9
--- /dev/null
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICpDCCAg2gAwIBAgICAm8wDQYJKoZIhvcNAQEEBQAwgakxCzAJBgNVBAYTAlVTMRIwEAYDVQQI
+EwlXaXNjb25zaW4xEDAOBgNVBAcTB01hZGlzb24xIDAeBgNVBAoTF1VuaXZlcnNpdHkgb2YgV2lz
+Y29uc2luMSswKQYDVQQLEyJEaXZpc2lvbiBvZiBJbmZvcm1hdGlvbiBUZWNobm9sb2d5MSUwIwYD
+VQQDExxIRVBLSSBTZXJ2ZXIgQ0EgLS0gMjAwMjA3MDFBMB4XDTAyMDcyNjA1MDg1M1oXDTA2MDkw
+NDA1MDg1M1owZjEQMA4GA1UEBhMHVW5rbm93bjEQMA4GA1UECBMHVW5rbm93bjEQMA4GA1UEChMH
+VW5rbm93bjEQMA4GA1UECxMHVW5rbm93bjEcMBoGA1UEAxMTc2hpYjIuaW50ZXJuZXQyLmVkdTCB
+nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAzFSvS9qa/UsH9oJH+u1QM7c51P67owRcqEURhTDs
+tT3WBDsP5+YTIGUiwJMkM4hQII6yMI7in6DzbhGQx9T/q6xRqXFXqLk1nrc/kcs+hbR4T11wwW6v
+d1k3uBUHJXV+OzvMEwz2SS0RxFZDw5MGlwJGqkwe5wPN6QUWzCxvpskCAwEAAaMdMBswDAYDVR0T
+AQH/BAIwADALBgNVHQ8EBAMCBaAwDQYJKoZIhvcNAQEEBQADgYEAhrSMGqkpC0zdL/m37A7g32le
+1kgi9PMJzgviXbG1k4eO+xl6JvSfHMfrcjtcHdH+IWZSEoJsKLhGbSSBcOCX34rm4RqE8h4ahgq7
+cDX2RCaY4D26R2cta7ZvXo7CUgJ7vbybSZ7QbqKs3yZcVXIL5sJXkhbZ3dnZRqiEm2VP9ZY=
+-----END CERTIFICATE-----
\ No newline at end of file
index 479236a..a6fa10f 100644 (file)
@@ -154,5 +154,36 @@ public class CredentialsTests extends TestCase {
                        fail("Failed to load credentials: " + e);
                }
        }
+       
+       public void testFileX509NoPassword() {
+
+               try {
+                       InputStream inStream = new FileInputStream("data/credentials2.xml");
+                       parser.parse(new InputSource(inStream));
+                       Credentials credentials = new Credentials(parser.getDocument().getDocumentElement());
+
+                       assertTrue("Credential could not be found.", credentials.containsCredential("test"));
+                       Credential credential = credentials.getCredential("test");
+
+                       assertTrue(
+                               "Credential was loaded with an incorrect type.",
+                               credential.getCredentialType() == Credential.X509);
+                       assertNotNull("Private key was not loaded correctly.", credential.getPrivateKey());
+                       assertEquals(
+                               "Unexpected X509 certificate found.",
+                               credential.getX509Certificate().getSubjectDN().getName(),
+                               "CN=shib2.internet2.edu, OU=Unknown, O=Unknown, ST=Unknown, C=Unknown");
+                       assertEquals(
+                               "Unexpected certificate chain length.",
+                               new Integer(credential.getX509CertificateChain().length),
+                               new Integer(3));
+                       assertEquals(
+                               "Unexpected X509 certificate found.",
+                               credential.getX509CertificateChain()[2].getSubjectDN().getName(),
+                               "CN=HEPKI Master CA -- 20020701A, OU=Division of Information Technology, O=University of Wisconsin, L=Madison, ST=Wisconsin, C=US");
+               } catch (Exception e) {
+                       fail("Failed to load credentials: " + e);
+               }
+       }
 
 }