+++ /dev/null
-/*
- * Copyright [2005] [University Corporation for Advanced Internet Development, Inc.]
- *
- * Licensed 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 edu.internet2.middleware.shibboleth.common;
-
-/**
- * Defines an IdP-wide caching mechanism.
- *
- * @author Walter Hoehn
- */
-public interface Cache {
-
- public enum CacheType {
- CLIENT_SIDE, SERVER_SIDE, CLIENT_SERVER_SHARED
- }
-
- /**
- * Returns the identifier for the cache. This will commonly be a string name for the subsytem that is accessing the
- * cache. Effectively acts as a namespace for the caching mechanisms.
- */
- public String getName();
-
- /**
- * Returns an indication of how the cache stores its data. Subsystems may enforce storage requirements on caches via
- * this mechanism.
- */
- public CacheType getCacheType();
-
- /**
- * Causes the cache to return a value associated with a given key.
- *
- * @throws CacheException
- * if an error was encountered while reading the cache
- */
- public String retrieve(String key) throws CacheException;
-
- /**
- * Causes the cache to remove a value associated with a given key.
- *
- * @throws CacheException
- * if an error was encountered while removing the value from the cache
- */
- public void remove(String key) throws CacheException;
-
- /**
- * Boolean indication of whether or not the cache contains a value tied to a specified key.
- *
- * @throws CacheException
- * if an error was encountered while reading the cache
- */
- public boolean contains(String key) throws CacheException;
-
- /**
- * Causes the cache to associate a value with a given key for a specified number of seconds.
- *
- * @throws CacheException
- * if the value could not be written to the cache
- */
- public void store(String key, String value, long duration) throws CacheException;
-}
+++ /dev/null
-/*
- * Copyright [2005] [University Corporation for Advanced Internet Development, Inc.]
- *
- * Licensed 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 edu.internet2.middleware.shibboleth.common;
-
-public class CacheException extends Exception {
-
- public CacheException(String message) {
-
- super(message);
- }
-}
+++ /dev/null
-/*
- * Copyright [2005] [University Corporation for Advanced Internet Development, Inc.]
- *
- * Licensed 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 edu.internet2.middleware.shibboleth.common;
-
-/**
- * @author Scott Cantor
- *
- */
-public class Constants {
-
- /** Shibboleth "transient" NameIdentifier Format */
- public static final String SHIB_NAMEID_FORMAT_URI = "urn:mace:shibboleth:1.0:nameIdentifier";
-
- /** Shibboleth attribute profile AttributeNamespace */
- public static final String SHIB_ATTRIBUTE_NAMESPACE_URI = "urn:mace:shibboleth:1.0:attributeNamespace:uri";
-
- /** Shibboleth AuthnRequest profile URI */
- public static final String SHIB_AUTHNREQUEST_PROFILE_URI = "urn:mace:shibboleth:1.0:profiles:AuthnRequest";
-}
+++ /dev/null
-/*
- * Copyright [2005] [University Corporation for Advanced Internet Development, Inc.]
- *
- * Licensed 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 edu.internet2.middleware.shibboleth.common;
-
-import java.security.Key;
-import java.security.PrivateKey;
-import java.security.cert.X509Certificate;
-import java.security.interfaces.DSAPrivateKey;
-import java.security.interfaces.RSAPrivateKey;
-
-/**
- * Used to prove identity or integrity of transmitted messages.
- *
- * @author Walter Hoehn
- */
-public class Credential {
-
- public static int UNKNOWN = 0;
- public static int RSA = 1;
- public static int DSA = 2;
-
- private int type = UNKNOWN;
- private Key key;
- private X509Certificate[] certs;
-
- /**
- * Creates a X509 credential.
- *
- * @param certChain
- * certificate chain corresponding to the private key
- * @param key
- * the RSA or DSA private key
- */
- public Credential(X509Certificate[] certChain, PrivateKey key) {
-
- if (key instanceof RSAPrivateKey) {
- type = RSA;
- } else if (key instanceof DSAPrivateKey) {
- type = DSA;
- }
- certs = certChain;
- this.key = key;
- }
-
- public int getCredentialType() {
-
- return type;
- }
-
- public String getKeyAlgorithm() {
-
- return key.getAlgorithm();
- }
-
- public PrivateKey getPrivateKey() {
-
- if (key instanceof PrivateKey) { return (PrivateKey) key; }
- return null;
- }
-
- public boolean hasX509Certificate() {
-
- if (certs == null || certs.length == 0) { return false; }
- return true;
- }
-
- public X509Certificate getX509Certificate() {
-
- return certs[0];
- }
-
- public X509Certificate[] getX509CertificateChain() {
-
- return certs;
- }
-}
+++ /dev/null
-/*
- * Copyright [2005] [University Corporation for Advanced Internet Development, Inc.]
- *
- * Licensed 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 edu.internet2.middleware.shibboleth.common;
-
-import org.w3c.dom.Element;
-
-/**
- * Defines a method for loading a credential from a particular storage mechanism.
- *
- * @author Walter Hoehn
- */
-public interface CredentialResolver {
-
- /**
- * Loads a credential as specified by the XML configuration.
- *
- * @param e
- * DOM representation of credential resolver configuration
- *
- * @return the credential
- *
- * @throws CredentialFactoryException
- * if the credential could not be loaded
- */
- Credential loadCredential(Element e) throws CredentialFactoryException;
-}
+++ /dev/null
-/*
- * Copyright [2005] [University Corporation for Advanced Internet Development, Inc.]
- *
- * Licensed 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 edu.internet2.middleware.shibboleth.common;
-
-import java.io.BufferedInputStream;
-import java.io.BufferedReader;
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.StringReader;
-import java.security.AlgorithmParameters;
-import java.security.GeneralSecurityException;
-import java.security.KeyFactory;
-import java.security.KeyStore;
-import java.security.KeyStoreException;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.security.PrivateKey;
-import java.security.Provider;
-import java.security.PublicKey;
-import java.security.Security;
-import java.security.Signature;
-import java.security.UnrecoverableKeyException;
-import java.security.cert.Certificate;
-import java.security.cert.CertificateException;
-import java.security.cert.CertificateFactory;
-import java.security.cert.X509Certificate;
-import java.security.spec.DSAPrivateKeySpec;
-import java.security.spec.InvalidKeySpecException;
-import java.security.spec.PKCS8EncodedKeySpec;
-import java.security.spec.RSAPrivateCrtKeySpec;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Enumeration;
-import java.util.Hashtable;
-import java.util.List;
-
-import javax.crypto.BadPaddingException;
-import javax.crypto.Cipher;
-import javax.crypto.EncryptedPrivateKeyInfo;
-import javax.crypto.SecretKey;
-import javax.crypto.SecretKeyFactory;
-import javax.crypto.spec.IvParameterSpec;
-import javax.crypto.spec.PBEKeySpec;
-import javax.crypto.spec.SecretKeySpec;
-
-import org.apache.log4j.Logger;
-import org.bouncycastle.asn1.ASN1InputStream;
-import org.bouncycastle.asn1.DEREncodable;
-import org.bouncycastle.asn1.DERInteger;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DERObjectIdentifier;
-import org.bouncycastle.asn1.DEROctetString;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.util.ASN1Dump;
-import org.bouncycastle.util.encoders.Base64;
-import org.w3c.dom.Element;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-
-/**
- * Uses {@link CredentialResolver}implementations to create {@link Credential}s.
- *
- * @author Walter Hoehn
- */
-public class Credentials {
-
- public static final String credentialsNamespace = "urn:mace:shibboleth:credentials:1.0";
-
- private static Logger log = Logger.getLogger(Credentials.class.getName());
- private Hashtable<String, Credential> data = new Hashtable<String, Credential>();
- private boolean singleMode = false;
-
- /**
- * Creates credentials based on XML configuration.
- *
- * @param e
- * DOM representation of credentials configuration
- */
- public Credentials(Element e) {
-
- if (e != null && e.getLocalName().equals("Credential")) {
- singleMode = true;
- } else if (e == null || !e.getLocalName().equals("Credentials")) { throw new IllegalArgumentException(); }
-
- NodeList resolverNodes = e.getChildNodes();
- if (resolverNodes.getLength() <= 0) {
- log.error("Credentials configuration inclues no Credential Resolver definitions.");
- throw new IllegalArgumentException("Cannot load credentials.");
- }
-
- for (int i = 0; resolverNodes.getLength() > i; i++) {
- if (resolverNodes.item(i).getNodeType() == Node.ELEMENT_NODE) {
- try {
- String credentialId = ((Element) resolverNodes.item(i)).getAttribute("Id");
- if (credentialId == null || credentialId.equals("")) {
- if (singleMode) {
- credentialId = "SINGLE";
- } else {
- log
- .error("Found credential that was not labeled with a unique \"Id\" attribute. Skipping.");
- }
- }
-
- if (data.containsKey(credentialId)) {
- log.error("Duplicate credential id (" + credentialId + ") found. Skipping");
- }
-
- log.info("Found credential (" + credentialId + "). Loading...");
- data.put(credentialId, CredentialFactory.loadCredential((Element) resolverNodes.item(i)));
-
- } catch (CredentialFactoryException cfe) {
- log.error("Could not load credential, skipping: " + cfe.getMessage());
- } catch (ClassCastException cce) {
- log.error("Problem realizing credential configuration " + cce.getMessage());
- }
- }
- }
- }
-
- public boolean containsCredential(String identifier) {
-
- return data.containsKey(identifier);
- }
-
- public Credential getCredential(String identifier) {
-
- // Default if there is only one credential
- if ((identifier == null || identifier.equals("")) && data.size() == 1) { return (Credential) data.values()
- .iterator().next(); }
-
- return data.get(identifier);
- }
-
- public Credential getCredential() {
-
- return data.values().iterator().next();
- }
-
- static class CredentialFactory {
-
- private static Logger log = Logger.getLogger(CredentialFactory.class.getName());
-
- public static Credential loadCredential(Element e) throws CredentialFactoryException {
-
- if (e.getLocalName().equals("KeyInfo")) { return new KeyInfoCredentialResolver().loadCredential(e); }
-
- if (e.getLocalName().equals("FileResolver")) { return new FileCredentialResolver().loadCredential(e); }
-
- if (e.getLocalName().equals("KeyStoreResolver")) { return new KeystoreCredentialResolver()
- .loadCredential(e); }
-
- if (e.getLocalName().equals("CustomResolver")) { return new CustomCredentialResolver().loadCredential(e); }
-
- log.error("Unrecognized Credential Resolver type: " + e.getTagName());
- throw new CredentialFactoryException("Failed to load credential.");
- }
-
- }
-
-}
-
-class KeyInfoCredentialResolver implements CredentialResolver {
-
- private static Logger log = Logger.getLogger(KeyInfoCredentialResolver.class.getName());
-
- KeyInfoCredentialResolver() throws CredentialFactoryException {
-
- log.error("Credential Resolver (KeyInfoCredentialResolver) not implemented");
- throw new CredentialFactoryException("Failed to load credential.");
- }
-
- public Credential loadCredential(Element e) {
-
- return null;
- }
-}
-
-/**
- * Loads a credential from a file. Supports DER, PEM, encrypted PEM, PKCS8, and encrypted PKCS8 for RSA and DSA.
- *
- * @author Walter Hoehn
- * @author Chad La Joie
- */
-
-class FileCredentialResolver implements CredentialResolver {
-
- private static Logger log = Logger.getLogger(FileCredentialResolver.class.getName());
-
- /**
- * Reads a private key, and certificate information, specified by the configuration element, and creates a security
- * credential which can then be used for operations such a assertion signing. DER and PEM encoded keys (both
- * none-encrypted and encrypted) and PEM encoded certificated are supported.
- *
- * @param e
- * the credentials configuration element
- * @throws CredentialFactoryException
- * thrown if an error is encountered during any step of the credential creation, exact error specified
- * in exception message
- */
- public Credential loadCredential(Element e) throws CredentialFactoryException {
-
- if (!e.getLocalName().equals("FileResolver")) {
- log.error("Invalid Credential Resolver configuration: expected <FileResolver> .");
- throw new CredentialFactoryException("Failed to initialize Credential Resolver.");
- }
-
- PrivateKey key = getPrivateKey(e);
- if (key == null) {
- log.error("Failed to load private key.");
- throw new CredentialFactoryException("Failed to load private key.");
- }
-
- List<Certificate> certChain = getCertificateChain(e, key);
-
- Credential credential = new Credential(((X509Certificate[]) certChain.toArray(new X509Certificate[0])), key);
- if (log.isDebugEnabled()) {
- log.debug("Credential created");
- }
-
- return credential;
- }
-
- /**
- * Gets the private key for the credentials. Keys can be in either DER or PEM format and either password protected
- * (encrypted) or not.
- *
- * @param credentialConfigElement
- * the credential configuration element
- * @return the private key
- * @throws CredentialFactoryException
- * thrown if the private key file can not be found, the private key format can not be determined, or
- * some IO error occurs reading from the private key file
- */
- private PrivateKey getPrivateKey(Element credentialConfigElement) throws CredentialFactoryException {
-
- String keyPath = getKeyPath(credentialConfigElement);
- String password = getKeyPassword(credentialConfigElement);
-
- InputStream keyStream = null;
- try {
- if (log.isDebugEnabled()) {
- log.debug("Attempting to load private key from file " + keyPath);
- }
- keyStream = new ShibResource(keyPath, this.getClass()).getInputStream();
- int encoding = getKeyEncodingFormat(credentialConfigElement, keyStream);
- EncodedKey encodedKey;
-
- switch (encoding) {
- case EncodedKey.DER_ENCODING :
- if (log.isDebugEnabled()) {
- log.debug("Private key in file " + keyPath + " determined to be DER encoded");
- }
- encodedKey = new DERKey(keyStream, password);
- return encodedKey.getPrivateKey();
-
- case EncodedKey.PEM_ENCODING :
- if (log.isDebugEnabled()) {
- log.debug("Private key in file " + keyPath + " determined to be PEM encoded");
- }
- encodedKey = new PEMKey(keyStream, password);
- return encodedKey.getPrivateKey();
-
- default :
- log.error("Unable to determine format of private key specified in file " + keyPath);
- throw new CredentialFactoryException("Unable to determine private key format.");
- }
- } catch (IOException ioe) {
- log.error("Could not load credential from specified file (" + keyPath + "): " + ioe);
- throw new CredentialFactoryException("Unable to load private key.");
- } finally {
- if (keyStream != null) {
- try {
- keyStream.close();
- } catch (IOException e1) {
- // ignore
- }
- }
- }
- }
-
- /**
- * Gets the complete certificate chain specified by the configuration element. Currently only X.509 certificates are
- * supported.
- *
- * @param credentialConfigElement
- * the Credentials configuration element
- * @param key
- * the private key for the certificate
- * @return the certificate chain as a list of certificates
- * @throws CredentialFactoryException
- * thrown if the certificate files is not found, can not be parsed, or an IOException occurs whils
- * reading the file
- */
- private List<Certificate> getCertificateChain(Element credentialConfigElement, PrivateKey key)
- throws CredentialFactoryException {
-
- List<Certificate> certChain = new ArrayList<Certificate>();
- String certPath = getCertPath(credentialConfigElement);
-
- if (certPath == null || certPath.equals("")) {
- if (log.isInfoEnabled()) {
- log.info("No certificates specified.");
- }
- } else {
- if (log.isDebugEnabled()) {
- log.debug("Certificate Path: (" + certPath + ").");
- }
-
- // A placeholder in case we want to make this configurable
- String certType = "X.509";
-
- // The loading code should work for other types, but the chain
- // construction code would break
- if (!certType.equals("X.509")) {
- log.error("File credential resolver only supports the X.509 certificates.");
- throw new CredentialFactoryException("Only X.509 certificates are supported");
- }
-
- ArrayList<Certificate> allCerts = new ArrayList<Certificate>();
-
- try {
- Certificate[] certsFromPath = loadCertificates(new ShibResource(certPath, this.getClass())
- .getInputStream(), certType);
-
- allCerts.addAll(Arrays.asList(certsFromPath));
-
- // Find the end-entity cert first
- if (certsFromPath == null || certsFromPath.length == 0) {
- log.error("File at (" + certPath + ") did not contain any valid certificates.");
- throw new CredentialFactoryException("File did not contain any valid certificates.");
- }
-
- if (certsFromPath.length == 1) {
- if (log.isDebugEnabled()) {
- log.debug("Certificate file only contains 1 certificate.");
- log.debug("Ensuring that it matches the private key.");
- }
- if (!isMatchingKey(certsFromPath[0].getPublicKey(), key)) {
- log.error("Certificate file " + certPath
- + "only contained one certificate and it does not match the private key.");
- throw new CredentialFactoryException(
- "No certificate in chain that matches specified private key");
- }
- certChain.add(certsFromPath[0]);
- if (log.isDebugEnabled()) {
- log.debug("Successfully identified the end entity cert: "
- + ((X509Certificate) certChain.get(0)).getSubjectDN());
- }
-
- } else {
- if (log.isDebugEnabled()) {
- log.debug("Certificate file contains multiple certificates.");
- log
- .debug("Trying to determine the end-entity cert by the matching certificates against the private key.");
- }
- for (int i = 0; certsFromPath.length > i; i++) {
- if (isMatchingKey(certsFromPath[i].getPublicKey(), key)) {
- if (log.isDebugEnabled()) {
- log.debug("Found matching end cert: "
- + ((X509Certificate) certsFromPath[i]).getSubjectDN());
- }
- certChain.add(certsFromPath[i]);
- }
- }
- if (certChain.size() < 1) {
- log.error("Certificate file " + certPath
- + "only contained multiple certificates and none matched the private key.");
- throw new CredentialFactoryException(
- "No certificate in chain that matches specified private key");
- }
- if (certChain.size() > 1) {
- log.error("More than one certificate in chain that matches specified private key");
- throw new CredentialFactoryException(
- "More than one certificate in chain that matches specified private key");
- }
- if (log.isDebugEnabled()) {
- log.debug("Successfully identified the end entity cert: "
- + ((X509Certificate) certChain.get(0)).getSubjectDN());
- }
- }
-
- // Now load additional certs and construct a chain
- String[] caPaths = getCAPaths(credentialConfigElement);
- if (caPaths != null && caPaths.length > 0) {
- if (log.isDebugEnabled()) {
- log
- .debug("Attempting to load certificates from (" + caPaths.length
- + ") CA certificate files.");
- }
- for (int i = 0; i < caPaths.length; i++) {
- allCerts.addAll(Arrays.asList(loadCertificates(new ShibResource(caPaths[i], this.getClass())
- .getInputStream(), certType)));
- }
- }
-
- if (log.isDebugEnabled()) {
- log.debug("Attempting to construct a certificate chain.");
- }
- walkChain((X509Certificate[]) allCerts.toArray(new X509Certificate[0]), certChain);
-
- if (log.isDebugEnabled()) {
- log.debug("Verifying that each link in the cert chain is signed appropriately");
- }
- for (int i = 0; i < certChain.size() - 1; i++) {
- PublicKey pubKey = ((X509Certificate) certChain.get(i + 1)).getPublicKey();
- try {
- ((X509Certificate) certChain.get(i)).verify(pubKey);
- } catch (Exception se) {
- log.error("Certificate chain cannot be verified: " + se);
- throw new CredentialFactoryException("Certificate chain cannot be verified: " + se);
- }
- }
- if (log.isDebugEnabled()) {
- log.debug("All signatures verified. Certificate chain creation successful.");
- }
-
- if (log.isInfoEnabled()) {
- log.info("Successfully loaded certificates.");
- }
- } catch (IOException ioe) {
- log.error("Could not load resource from specified location (" + certPath + "): " + ioe);
- throw new CredentialFactoryException("Unable to load certificates.");
- }
- }
-
- return certChain;
- }
-
- /**
- * Determines whether the key is PEM or DER encoded.
- *
- * @param e
- * the file credential resolver configuration element
- * @param keyStream
- * an input stream reading the private key
- * @return the encoding format of the key
- * @throws CredentialFactoryException
- * thrown if the key format can not be determined or the key can not be read
- */
- private int getKeyEncodingFormat(Element e, InputStream keyStream) throws CredentialFactoryException {
-
- NodeList keyElements = e.getElementsByTagNameNS(Credentials.credentialsNamespace, "Key");
- if (keyElements.getLength() < 1) {
- log.error("No private key specified in file credential resolver");
- throw new CredentialFactoryException("File Credential Resolver requires a <Key> specification.");
- }
-
- if (keyElements.getLength() > 1) {
- log.error("Multiple Key path specifications, using first.");
- }
-
- String formatStr = ((Element) keyElements.item(0)).getAttribute("format");
-
- if (formatStr != null && formatStr.length() > 0) {
- if (formatStr.equals("PEM")) {
- return EncodedKey.PEM_ENCODING;
- } else if (formatStr.equals("DER")) {
- return EncodedKey.DER_ENCODING;
- } else if (formatStr.equals("PKCS12")) {
- log.error("PKCS12 private keys are not yet supported");
- return -1;
- }
- }
-
- if (log.isInfoEnabled()) {
- log
- .info("Private key format was not specified in file credential resolver configuration, attempting to auto-detect it.");
- }
- try {
- // Need to mark the stream and then reset it, after getting the
- // first byte so that the private key decoder starts reading at
- // the correct position
- keyStream.mark(2);
- int firstByte = keyStream.read();
- keyStream.reset();
-
- // PEM encoded keys must start with a "-", a decimal value of 45
- if (firstByte == 45) { return EncodedKey.PEM_ENCODING; }
-
- // DER encoded keys must start with a decimal value of 48
- if (firstByte == 48) { return EncodedKey.DER_ENCODING; }
-
- // Can not determine type
- return -1;
- } catch (IOException ioe) {
- throw new CredentialFactoryException(
- "Could not determine the type of private key for file credential resolver.");
- }
- }
-
- /**
- * Gets the private key password from the Credentials configuration element if one exists.
- *
- * @param e
- * the credentials configuration element
- * @return the password if one is given or an empty string if one is not
- * @throws CredentialFactoryException
- * thrown if no Key element is present in the configuration
- */
- private String getKeyPassword(Element e) throws CredentialFactoryException {
-
- NodeList keyElements = e.getElementsByTagNameNS(Credentials.credentialsNamespace, "Key");
- if (keyElements.getLength() < 1) {
- log.error("Key not specified.");
- throw new CredentialFactoryException("File Credential Resolver requires a <Key> specification.");
- }
-
- if (keyElements.getLength() > 1) {
- log.error("Multiple Key path specifications, using first.");
- }
-
- String password = ((Element) keyElements.item(0)).getAttribute("password");
- if (password == null) {
- password = "";
- }
- return password;
- }
-
- /**
- * Gets the certificate path from the Credentials configuration element. If multiple paths are specified only the
- * first one is used.
- *
- * @param e
- * the credentials configuration element
- * @return the certificate path, or null if non is specificed
- * @throws CredentialFactoryException
- * thrown if no Path element is given or it's empty
- */
- private String getCertPath(Element e) throws CredentialFactoryException {
-
- NodeList certificateElements = e.getElementsByTagNameNS(Credentials.credentialsNamespace, "Certificate");
- if (certificateElements.getLength() < 1) {
- if (log.isDebugEnabled()) {
- log.debug("No <Certificate> element found.");
- }
- return null;
- }
-
- 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, none was specified.");
- }
-
- 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 was empty.");
- throw new CredentialFactoryException(
- "File Credential Resolver requires a <Certificate><Path/></Certificate> specification, the specified one was empty.");
- }
-
- return path;
- }
-
- /**
- * Get the CA certificate paths from the Credentials configuration element. Paths should be delimited with the
- * operating system path delimiter. If multiple Certificate elements are found only the first is used.
- *
- * @param e
- * the credentials configuration element
- * @return an array of CA certificate paths, or null if no certificate path was specified
- * @throws CredentialFactoryException
- * no certificate path was specified
- */
- private String[] getCAPaths(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, "CAPath");
- if (pathElements.getLength() < 1) {
- if (log.isDebugEnabled()) {
- log.debug("No CA Certificate paths specified.");
- }
- return null;
- }
- ArrayList<String> paths = new ArrayList<String>();
- for (int i = 0; i < pathElements.getLength(); i++) {
- Node tnode = pathElements.item(i).getFirstChild();
- String path = null;
- if (tnode != null && tnode.getNodeType() == Node.TEXT_NODE) {
- path = tnode.getNodeValue();
- }
- if (path != null && !(path.equals(""))) {
- paths.add(path);
- }
- if (paths.isEmpty()) {
- if (log.isDebugEnabled()) {
- log.debug("No CA Certificate paths specified.");
- }
- }
- }
- return (String[]) paths.toArray(new String[0]);
- }
-
- /**
- * Gets the path to the private key from the Credentials configuration element. If more than one is specified only
- * the first one is used.
- *
- * @param e
- * the credentials configuration element
- * @return path to the private key
- * @throws CredentialFactoryException
- * thrown if no path is specified or it's null.
- */
- private String getKeyPath(Element e) throws CredentialFactoryException {
-
- NodeList keyElements = e.getElementsByTagNameNS(Credentials.credentialsNamespace, "Key");
- if (keyElements.getLength() < 1) {
- log.error("Key not specified.");
- throw new CredentialFactoryException("File Credential Resolver requires a <Key> specification.");
- }
- if (keyElements.getLength() > 1) {
- log.error("Multiple Key path specifications, using first.");
- }
-
- NodeList pathElements = ((Element) keyElements.item(0)).getElementsByTagNameNS(
- Credentials.credentialsNamespace, "Path");
- if (pathElements.getLength() < 1) {
- log.error("Key path not specified.");
- throw new CredentialFactoryException(
- "File Credential Resolver requires a <Key><Path/></Certificate> specification.");
- }
- if (pathElements.getLength() > 1) {
- log.error("Multiple Key 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("Key path is empty.");
- throw new CredentialFactoryException(
- "File Credential Resolver requires a <Key><Path/></Certificate> specification.");
- }
- return path;
- }
-
- /**
- * Loads a specified bundle of certs individually and returns an array of {@link Certificate}objects. This is
- * needed because the standard {@link CertificateFactory#getCertificates(InputStream)}method bails out when it has
- * trouble loading any cert and cannot handle "comments".
- */
- private Certificate[] loadCertificates(InputStream inStream, String certType) throws CredentialFactoryException {
-
- ArrayList<Certificate> certificates = new ArrayList<Certificate>();
-
- try {
- CertificateFactory certFactory = CertificateFactory.getInstance(certType);
-
- BufferedReader in = new BufferedReader(new InputStreamReader(inStream));
- String str;
- boolean insideCert = false;
- StringBuffer rawCert = null;
- while ((str = in.readLine()) != null) {
-
- if (insideCert) {
- rawCert.append(str);
- rawCert.append(System.getProperty("line.separator"));
- if (str.matches("^.*-----END CERTIFICATE-----.*$")) {
- insideCert = false;
- try {
- Certificate cert = certFactory.generateCertificate(new ByteArrayInputStream(rawCert
- .toString().getBytes()));
- certificates.add(cert);
- } catch (CertificateException ce) {
- log.warn("Failed to load a certificate from the certificate bundle: " + ce);
- if (log.isDebugEnabled()) {
- if (log.isDebugEnabled()) {
- log.debug("Dump of bad certificate: " + System.getProperty("line.separator")
- + rawCert.toString());
- }
- }
- }
- continue;
- }
- } else if (str.matches("^.*-----BEGIN CERTIFICATE-----.*$")) {
- insideCert = true;
- rawCert = new StringBuffer();
- rawCert.append(str);
- rawCert.append(System.getProperty("line.separator"));
- }
- }
- in.close();
- } catch (IOException p) {
- log.error("Could not load resource from specified location: " + p);
- throw new CredentialFactoryException("Unable to load certificates.");
- } catch (CertificateException p) {
- log.error("Problem loading certificate factory: " + p);
- throw new CredentialFactoryException("Unable to load certificates.");
- }
-
- return (Certificate[]) certificates.toArray(new Certificate[0]);
- }
-
- /**
- * Given an ArrayList containing a base certificate and an array of unordered certificates, populates the ArrayList
- * with an ordered certificate chain, based on subject and issuer.
- *
- * @param chainSource
- * array of certificates to pull from
- * @param chainDest
- * ArrayList containing base certificate
- * @throws InvalidCertificateChainException
- * thrown if a chain cannot be constructed from the specified elements
- */
- protected void walkChain(X509Certificate[] chainSource, List<Certificate> chainDest)
- throws CredentialFactoryException {
-
- X509Certificate currentCert = (X509Certificate) chainDest.get(chainDest.size() - 1);
- if (currentCert.getSubjectDN().equals(currentCert.getIssuerDN())) {
- if (log.isDebugEnabled()) {
- log.debug("Found self-signed root cert: " + currentCert.getSubjectDN());
- }
- return;
- } else {
- for (int i = 0; chainSource.length > i; i++) {
- if (currentCert.getIssuerDN().equals(chainSource[i].getSubjectDN())) {
- chainDest.add(chainSource[i]);
- walkChain(chainSource, chainDest);
- return;
- }
- }
- if (log.isDebugEnabled()) {
- log.debug("Certificate chain is incomplete.");
- }
- }
- }
-
- /**
- * Boolean indication of whether a given private key and public key form a valid keypair.
- *
- * @param pubKey
- * the public key
- * @param privKey
- * the private key
- */
- protected boolean isMatchingKey(PublicKey pubKey, PrivateKey privKey) {
-
- try {
- String controlString = "asdf";
- if (log.isDebugEnabled()) {
- log.debug("Checking for matching private key/public key pair");
- }
-
- Signature signature = null;
- try {
- signature = Signature.getInstance(privKey.getAlgorithm());
- } catch (NoSuchAlgorithmException nsae) {
- if (log.isDebugEnabled()) {
- log.debug("No provider for (RSA) signature, attempting (MD5withRSA).");
- }
- if (privKey.getAlgorithm().equals("RSA")) {
- signature = Signature.getInstance("MD5withRSA");
- } else {
- throw nsae;
- }
- }
- signature.initSign(privKey);
- signature.update(controlString.getBytes());
- byte[] sigBytes = signature.sign();
- signature.initVerify(pubKey);
- signature.update(controlString.getBytes());
- if (signature.verify(sigBytes)) {
- if (log.isDebugEnabled()) {
- log.debug("Found match.");
- }
- return true;
- }
- } catch (Exception e) {
- log.warn(e);
- }
- if (log.isDebugEnabled()) {
- log.debug("This pair does not match.");
- }
- return false;
- }
-
- /**
- * 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 initSize, int growBy) {
-
- buffer = new byte[initSize];
- this.cushion = growBy;
- }
-
- private void grow() {
-
- 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];
- System.arraycopy(buffer, 0, b, 0, currentSize);
- 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++;
- }
-
- }
-
- /**
- * Abstract class representing private keys encoded in formats like PEM and DER.
- *
- * @author Chad La Joie
- */
- private abstract class EncodedKey {
-
- /**
- * DER encoded key
- */
- public static final int DER_ENCODING = 0;
-
- /**
- * PEM encoded key
- */
- public static final int PEM_ENCODING = 1;
-
- /**
- * OID for DSA keys
- */
- public final static String DSAKey_OID = "1.2.840.10040.4.1";
-
- /**
- * OID for RSA keys
- */
- public final static String RSAKey_OID = "1.2.840.113549.1.1.1";
-
- /**
- * PKCS8 key format
- */
- public final static int PKCS8 = 0;
-
- /**
- * RSA key format
- */
- public final static int RSA = 1;
-
- /**
- * DSA key format
- */
- public final static int DSA = 2;
-
- /**
- * Key encryption algorithim DES-CDC
- */
- public final static int DES_CBC = 0;
-
- /**
- * Key encryption algorithim DES-EDE3-CBC
- */
- public final static int DES_EDE3_CBC = 1;
-
- /**
- * Format of the PEM encoded key
- */
- private int format = -1;
-
- /**
- * Is the key encrypted?
- */
- private boolean encrypted;
-
- /**
- * Password for the encrypted key
- */
- private String keyPassword;
-
- /**
- * Encryption algorithim used for this key
- */
- private int encAlgo = -1;
-
- /**
- * Initialization vector for the encryption algorithim
- */
- private String initVector = "";
-
- /**
- * DER encoded key
- */
- private byte[] keyBytes;
-
- /**
- * Gets the format (PKCS8, RSA, DSA) of the key.
- *
- * @return format of the key
- */
- public int getFormat() {
-
- return format;
- }
-
- /**
- * Sets the format (PKCS8, RSA, DSA) of the key.
- *
- * @param format
- * the format of the key
- */
- public void setFormat(int format) {
-
- this.format = format;
- }
-
- /**
- * Gets whether this PEM key is encrypted.
- *
- * @return true if this key is encrypted, false if not
- */
- public boolean isEncrypted() {
-
- return encrypted;
- }
-
- /**
- * Sets whether the key is encrypted.
- *
- * @param encrypted
- * whether the key is encrypted
- */
- public void setEncrypted(boolean encrypted) {
-
- this.encrypted = encrypted;
- }
-
- /**
- * Gets the password to decrypt this key
- *
- * @return the password to decrypt this key
- */
- public String getEncryptionPassword() {
-
- return keyPassword;
- }
-
- /**
- * Sets the password to decrypt this key
- *
- * @param keyPassword
- * the password to decrypt this key
- */
- public void setEncryptionPassword(String keyPassword) {
-
- this.keyPassword = keyPassword;
- }
-
- /**
- * Gets the encryption algorithim used to encrypt the private key.
- *
- * @return the encryption algorithim used to encrypt the private key
- */
- public int getEncryptionAlgorithim() {
-
- return encAlgo;
- }
-
- /**
- * Sets the encryption algorithim used to encrypt the private key.
- *
- * @param encAlgo
- * the encryption algorithim used to encrypt the private key
- */
- public void setEncryptionAlgorithim(int encAlgo) {
-
- this.encAlgo = encAlgo;
- }
-
- /**
- * Gets the initialization vector used in the encryption of the private key.
- *
- * @return the initialization vector used in the encryption of the private key
- */
- public String getInitializationVector() {
-
- return initVector;
- }
-
- /**
- * Sets the initialization vector used in the encryption of the private key.
- *
- * @param initVector
- * ets the initialization vector used in the encryption of the private key
- */
- public void setInitializationVector(String initVector) {
-
- this.initVector = initVector;
- }
-
- /**
- * Gets the private key as bytes.
- *
- * @return the private key as bytes.
- */
- public byte[] getKeyBytes() {
-
- return keyBytes;
- }
-
- /**
- * Sets the private key as bytes.
- *
- * @param keyBytes
- * the private key as bytes
- */
- public void setKeyBytes(byte[] keyBytes) {
-
- this.keyBytes = keyBytes;
- }
-
- /**
- * Gets the private key from this encoded key.
- *
- * @return the private key from this encoded key
- */
- public abstract PrivateKey getPrivateKey() throws CredentialFactoryException;
- }
-
- /**
- * Represents a PEM formatted cryptographic key. Used to determine it's format (PKCS8, RSA, DSA), whether it's been
- * encrypted or not, get the Base64 encoded key, and then decoded the key into the DER encoded key.
- *
- * @author Chad La Joie
- */
- private class PEMKey extends EncodedKey {
-
- /**
- * DER encoded key
- */
- private DERKey derKey;
-
- /**
- * Constructor
- *
- * @param pemKey
- * the PEM key
- * @throws CredentialFactoryException
- * @throws CredentialFactoryException
- * @throws IOException
- */
- public PEMKey(String pemKey, String password) throws IOException, CredentialFactoryException {
-
- setEncryptionPassword(password);
- BufferedReader keyReader = new BufferedReader(new StringReader(pemKey));
- parsePEMKey(keyReader);
- }
-
- /**
- * Constructor
- *
- * @param pemKeyStream
- * and input stream with the PEM key
- * @throws CredentialFactoryException
- * @throws CredentialFactoryException
- * @throws IOException
- */
- public PEMKey(InputStream pemKeyStream, String password) throws IOException, CredentialFactoryException {
-
- setEncryptionPassword(password);
- BufferedReader keyReader = new BufferedReader(new InputStreamReader(pemKeyStream));
- parsePEMKey(keyReader);
- }
-
- /**
- * Gets the private key from this PEM encoded key
- *
- * @throws CredentialFactoryException
- */
- public PrivateKey getPrivateKey() throws CredentialFactoryException {
-
- return derKey.getPrivateKey();
- }
-
- /**
- * Parses the PEM key to determine its format, whether it's encrypted, then extract the Base64 encoded key and
- * decodes it into the DER encoded key.
- *
- * @param keyReader
- * the PEM key
- * @throws IOException
- * thrown if there is problem reading the key
- * @throws CredentialFactoryException
- */
- private void parsePEMKey(BufferedReader keyReader) throws IOException, CredentialFactoryException {
-
- if (log.isDebugEnabled()) {
- log.debug("Parsing PEM enocded private key");
- }
- String currentLine = keyReader.readLine();
-
- if (currentLine.matches("^.*-----BEGIN PRIVATE KEY-----.*$")) {
- if (log.isDebugEnabled()) {
- log.debug("Key appears to be in PKCS8 format.");
- }
-
- setFormat(PKCS8);
- setEncrypted(false);
-
- } else if (currentLine.matches("^.*-----BEGIN ENCRYPTED PRIVATE KEY-----.*$")) {
- if (log.isDebugEnabled()) {
- log.debug("Key appears to be in encrypted PKCS8 format.");
- }
- setFormat(PKCS8);
- setEncrypted(true);
-
- } else if (currentLine.matches("^.*-----BEGIN RSA PRIVATE KEY-----.*$")) {
- setFormat(RSA);
-
- // Mark the stream, if it's not encrypted we need to reset
- // or lose the first line of the base64 key
- keyReader.mark(100);
- currentLine = keyReader.readLine();
- if (currentLine.matches("^.*Proc-Type: 4,ENCRYPTED.*$")) {
- if (log.isDebugEnabled()) {
- log.debug("Key appears to be encrypted RSA in raw format.");
- }
- setEncrypted(true);
- } else {
- if (log.isDebugEnabled()) {
- log.debug("Key appears to be RSA in raw format.");
- }
- keyReader.reset();
- setEncrypted(false);
- }
-
- } else if (currentLine.matches("^.*-----BEGIN DSA PRIVATE KEY-----.*$")) {
- setFormat(DSA);
-
- // Mark the stream, if it's not encrypted we need to reset
- // or lose the first line of the base64 key
- keyReader.mark(100);
- currentLine = keyReader.readLine();
- if (currentLine.matches("^.*Proc-Type: 4,ENCRYPTED.*$")) {
- if (log.isDebugEnabled()) {
- log.debug("Key appears to be encrypted DSA in raw format.");
- }
- setEncrypted(true);
- } else {
- if (log.isDebugEnabled()) {
- log.debug("Key appears to be DSA in raw format.");
- }
- keyReader.reset();
- setEncrypted(false);
- }
- }
-
- // Key is an encrypted RSA or DSA key, need to get the algorithim used
- if (isEncrypted() && (getFormat() == RSA || getFormat() == DSA)) {
- if (log.isDebugEnabled()) {
- log.debug("Key data is encrypted RSA or DSA, inspecting encryption properties");
- }
- currentLine = keyReader.readLine();
- String[] components = currentLine.split(":\\s");
- if (components.length != 2) {
- log.error("Encrypted key did not contain DEK-Info specification.");
- // throw new CredentialFactoryException("Unable to load private key.");
- }
- String[] cryptData = components[1].split(",");
- if (cryptData.length != 2 || cryptData[0] == null || cryptData[0].equals("") || cryptData[1] == null
- || cryptData[1].equals("")) {
- log.error("Encrypted key did not contain a proper DEK-Info specification.");
- // throw new CredentialFactoryException("Unable to load private key.");
- }
- if (cryptData[0].equals("DES-CBC")) {
- if (log.isDebugEnabled()) {
- log.debug("Key encryption method determined to be DES-CBC");
- }
- setEncryptionAlgorithim(DES_CBC);
- } else if (cryptData[0].equals("DES-EDE3-CBC")) {
- if (log.isDebugEnabled()) {
- log.debug("Key encryption method determined to be DES-EDE3-CBC");
- }
- setEncryptionAlgorithim(DES_EDE3_CBC);
- } else {
- setEncryptionAlgorithim(-1);
- log.error("Key encryption method unknown: " + cryptData[0]);
- }
-
- if (log.isDebugEnabled()) {
- log.debug("Key encryption algorithim initialization vector determined to be " + cryptData[1]);
- }
- setInitializationVector(cryptData[1]);
- }
-
- // Now that we've parsed the headers, get the base64 encoded key itself
- StringBuffer keyBuf = new StringBuffer();
- while ((currentLine = keyReader.readLine()) != null) {
- if (currentLine.matches("^.*END.*$")) {
- break;
- }
-
- keyBuf.append(currentLine);
- }
-
- String base64Key = keyBuf.toString();
- if (log.isDebugEnabled()) {
- log.debug("Base64 encoded key: " + base64Key);
- }
-
- // Base64 decode the key, gives teh DER encoded key data
- if (log.isDebugEnabled()) {
- log.debug("Base64 decoding key");
- }
- setKeyBytes(Base64.decode(base64Key));
-
- // If the key was a raw RSA/DSA encrypted we need to decrypt it now
- // If it was a PKCS8 key we'll decrypt it when we parse it's DER data
- if (isEncrypted() && (getFormat() == RSA || getFormat() == DSA)) {
- if (log.isDebugEnabled()) {
- log.debug("Decrypting RSA/DSA key");
- }
- decryptKey();
- }
-
- // We now have a key encoded in DER format
- if (log.isDebugEnabled()) {
- log.debug("PEM key has been decoded into DER encoded data, processing it as DER key");
- }
- derKey = new DERKey(getKeyBytes(), getEncryptionPassword());
-
- // Close the reader, we're done
- keyReader.close();
- }
-
- /**
- * Decrypts an encrypted private key.
- *
- * @throws CredentialFactoryException
- */
- private void decryptKey() throws CredentialFactoryException {
-
- try {
- byte[] ivBytes = new byte[8];
- for (int j = 0; j < 8; j++) {
- ivBytes[j] = (byte) Integer.parseInt(getInitializationVector().substring(j * 2, j * 2 + 2), 16);
- }
- IvParameterSpec paramSpec = new IvParameterSpec(ivBytes);
-
- byte[] keyBuffer = new byte[24];
- // The key generation method (with the IV used as the salt, and
- // the single proprietary iteration)
- // is the reason we can't use the pkcs5 providers to read the
- // OpenSSL encrypted format
-
- byte[] keyPass = getEncryptionPassword().getBytes();
- MessageDigest md = MessageDigest.getInstance("MD5");
- md.update(keyPass);
- md.update(paramSpec.getIV());
- byte[] digested = md.digest();
- System.arraycopy(digested, 0, keyBuffer, 0, 16);
-
- md.update(digested);
- md.update(keyPass);
- md.update(paramSpec.getIV());
- digested = md.digest();
- System.arraycopy(digested, 0, keyBuffer, 16, 8);
-
- SecretKeySpec keySpec = null;
- Cipher cipher = null;
- if (getEncryptionAlgorithim() == EncodedKey.DES_CBC) {
- // Special handling!!!
- // For DES, we use the same key generation,
- // then just chop off the end :-)
- byte[] desBuff = new byte[8];
- System.arraycopy(keyBuffer, 0, desBuff, 0, 8);
- keySpec = new SecretKeySpec(desBuff, "DES");
- cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
- }
- if (getEncryptionAlgorithim() == EncodedKey.DES_EDE3_CBC) {
- keySpec = new SecretKeySpec(keyBuffer, "DESede");
- cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
- }
-
- cipher.init(Cipher.DECRYPT_MODE, keySpec, paramSpec);
- byte[] decrypted = cipher.doFinal(getKeyBytes());
-
- setEncrypted(false);
- setKeyBytes(decrypted);
- } catch (BadPaddingException e) {
- log.error("Incorrect password to unlock private key.", e);
- throw new CredentialFactoryException("Unable to load private key.");
- } catch (Exception e) {
- log
- .error("Unable to decrypt private key. Installed JCE implementations don't support the necessary algorithm: "
- + e);
- throw new CredentialFactoryException("Unable to load private key.");
- }
- }
- }
-
- /**
- * Represents a DER formatted cryptographic key. Used to determine it's format (PKCS8, RSA, DSA), whether it's been
- * encrypted or not
- *
- * @author Chad La Joie
- */
- private class DERKey extends EncodedKey {
-
- DERSequence rootDerTag;
-
- /**
- * Constructor.
- *
- * @param derKeyStream
- * the inputstream that contains the key
- * @throws IOException
- * thrown if there is an error reading from the stream
- * @throws CredentialFactoryException
- * thrown if there is an error parsing the stream data
- */
- public DERKey(InputStream derKeyStream, String password) throws IOException, CredentialFactoryException {
-
- setEncryptionPassword(password);
- ByteContainer derKey = new ByteContainer(600, 50);
-
- for (int i = derKeyStream.read(); i != -1; i = derKeyStream.read()) {
- derKey.append((byte) i);
- }
-
- setKeyBytes(derKey.toByteArray());
- parseDerKey();
- }
-
- public DERKey(byte[] derKey, String password) throws IOException, CredentialFactoryException {
-
- setEncryptionPassword(password);
- setKeyBytes(derKey);
- parseDerKey();
- }
-
- public PrivateKey getPrivateKey() throws CredentialFactoryException {
-
- switch (getFormat()) {
- case EncodedKey.PKCS8 :
- if (!isEncrypted()) {
- return getPkcs8Key();
- } else {
- return getEncryptedPkcs8Key();
- }
-
- case EncodedKey.RSA :
- return getRSARawDerKey();
-
- case EncodedKey.DSA :
- return getDSARawDerKey();
-
- default :
- throw new CredentialFactoryException("Unable to determine format of DER encoded private key");
- }
- }
-
- /**
- * Takes a set of ASN.1 encoded bytes and converts them into a DER object.
- *
- * @param keyBytes
- * the ASN.1 encoded bytes
- * @return the DER object
- * @throws IOException
- * thrown if the bytes aren't ASN.1 encoded
- */
- private DERObject getRootDerTag(byte[] keyBytes) throws IOException {
-
- InputStream derKeyStream = new BufferedInputStream(new ByteArrayInputStream(getKeyBytes()));
- ASN1InputStream asn1Stream = new ASN1InputStream(derKeyStream);
- DERObject derObject = asn1Stream.readObject();
- derKeyStream.close();
- asn1Stream.close();
-
- return derObject;
- }
-
- /**
- * Parse the key stream and determines data about the key.
- *
- * @param derKeyStream
- * the inputstream that contains the key
- * @throws IOExceptionthrown
- * if there is an error reading from the stream
- * @throws CredentialFactoryException
- * thrown if there is an error parsing the stream data
- */
- private void parseDerKey() throws IOException, CredentialFactoryException {
-
- if (log.isDebugEnabled()) {
- log.debug("Starting to parse " + getKeyBytes().length + " byte DER formatted key.");
- }
- DERObject derObject = getRootDerTag(getKeyBytes());
-
- if (log.isDebugEnabled()) {
- log
- .debug("Parsed ASN.1 object which has the following structure:\n"
- + ASN1Dump.dumpAsString(derObject));
- }
-
- // All supported key formats start with a DER sequence tag
- if (!(derObject instanceof DERSequence)) {
- log.error("Private key is not in valid DER format, it does not start with a DER sequence");
- throw new CredentialFactoryException("Private key is not in valid DER format");
- }
- DERSequence rootSeq = (DERSequence) derObject;
- if (rootSeq.size() < 2) {
- // Valid key in any format will have at least two tags under the root
- log.error("Private key is not in valid DER format; does not contain more than 2 ASN.1 tags");
- throw new CredentialFactoryException("Private key is not in valid DER format");
- }
-
- DERObject firstChild = rootSeq.getObjectAt(0).getDERObject();
-
- if (firstChild instanceof DERSequence) {
- if (log.isDebugEnabled()) {
- log.debug("First ASN.1 tag is a sequence, checking to see if this is an encrypted PKCS8 key");
- }
- // Might be encrypted PKCS8, lets check some more
- DERSequence firstChildSeq = (DERSequence) firstChild;
- DERObject grandChildObj = firstChildSeq.getObjectAt(0).getDERObject();
- DERObject secondChild = rootSeq.getObjectAt(1).getDERObject();
-
- // Encrypted PKCS8 have an octet string as the second child (from the root)
- // and an object identifier as the child of the first child from the root
- if (secondChild instanceof DEROctetString && grandChildObj instanceof DERObjectIdentifier) {
- if (log.isDebugEnabled()) {
- log.debug("DER encoded key determined to be encrypted PKCS8");
- }
- rootDerTag = rootSeq;
- setFormat(PKCS8);
- setEncrypted(true);
- }
- } else if (firstChild instanceof DERInteger) {
- if (log.isDebugEnabled()) {
- log
- .debug("First child ASN.1 tag is a Integer, checking to see if this is an PKCS8, RSA, or DSA key");
- }
- // Might be unencrypted PKCS8, RSA, or DSA
-
- // Check to see if it's PKCS8 with contains an
- // Integer, then Sequence, then OctetString
- if (rootSeq.size() == 3) {
- if (log.isDebugEnabled()) {
- log.debug("First ASN.1 sequence tag has 3 children, checking to see if this is an PKCS8 key");
- }
- if (rootSeq.getObjectAt(0).getDERObject() instanceof DERInteger
- && rootSeq.getObjectAt(1).getDERObject() instanceof DERSequence
- && rootSeq.getObjectAt(2).getDERObject() instanceof DEROctetString) {
- if (log.isDebugEnabled()) {
- log.debug("DER encoded key determined to be PKCS8");
- }
- rootDerTag = rootSeq;
- setFormat(PKCS8);
- setEncrypted(false);
- }
- } else {
- // Might be RSA or DSA. DSA will have 6 Integers
- // under the root sequences, RSA will have 9
- Enumeration children = rootSeq.getObjects();
- DERObject child;
- boolean allInts = true;
-
- while (children.hasMoreElements()) {
- child = ((DEREncodable) children.nextElement()).getDERObject();
- if (!(child instanceof DERInteger)) {
- allInts = false;
- }
- }
-
- if (rootSeq.size() == 6) {
- if (log.isDebugEnabled()) {
- log.debug("First ASN.1 sequence tag has 6 children, checking to see if this is an DSA key");
- }
- // DSA keys have six integer tags in the root sequence
- if (allInts) {
- if (log.isDebugEnabled()) {
- log.debug("DER encoded key determined to be raw DSA");
- }
- rootDerTag = rootSeq;
- setFormat(DSA);
- setEncrypted(false);
- }
- } else if (rootSeq.size() == 9) {
- if (log.isDebugEnabled()) {
- log.debug("First ASN.1 sequence tag has 9 children, checking to see if this is an DSA key");
- }
- // RSA (PKCS1) keys have 9 integer tags in the root sequence
- if (allInts) {
- if (log.isDebugEnabled()) {
- log.debug("DER encoded key determined to be raw RSA");
- }
- rootDerTag = rootSeq;
- setFormat(RSA);
- setEncrypted(false);
- }
- }
- }
- }
-
- // If we don't know what the format is now then the stream wasn't a valid DER encoded key
- if (getFormat() == -1) {
- log.error("Private key is not in valid DER format");
- throw new CredentialFactoryException("Private key is not in valid DER format");
- }
- }
-
- /**
- * Gets the private key from a encrypted PKCS8 formatted key.
- *
- * @param bytes
- * the PKCS8 formatted key
- * @param password
- * the password to decrypt the key
- * @return the private key
- * @throws CredentialFactoryException
- * thrown is there is an error loading the private key
- */
- private PrivateKey getEncryptedPkcs8Key() throws CredentialFactoryException {
-
- if (log.isDebugEnabled()) {
- log.debug("Beginning to decrypt encrypted PKCS8 key");
- }
- try {
- // Convince the JCE provider that it does know how to do
- // pbeWithMD5AndDES-CBC
- Provider provider = Security.getProvider("SunJCE");
- if (provider != null) {
- provider.setProperty("Alg.Alias.AlgorithmParameters.1.2.840.113549.1.5.3", "PBE");
- provider.setProperty("Alg.Alias.SecretKeyFactory.1.2.840.113549.1.5.3", "PBEWithMD5AndDES");
- provider.setProperty("Alg.Alias.Cipher.1.2.840.113549.1.5.3", "PBEWithMD5AndDES");
- }
-
- if (log.isDebugEnabled()) {
- log.debug("Inspecting key properties");
- }
- EncryptedPrivateKeyInfo encryptedKeyInfo = new EncryptedPrivateKeyInfo(getKeyBytes());
- if (log.isDebugEnabled()) {
- log.debug("Key encryption Algorithim: " + encryptedKeyInfo.getAlgName());
- log.debug("Key encryption parameters: " + encryptedKeyInfo.getAlgParameters());
- }
-
- AlgorithmParameters params = encryptedKeyInfo.getAlgParameters();
-
- if (params == null) {
- log.error("Unable to decrypt private key. Installed JCE implementations don't support the ("
- + encryptedKeyInfo.getAlgName() + ") algorithm.");
- throw new CredentialFactoryException("Unable to load private key; " + encryptedKeyInfo.getAlgName()
- + " is not a supported by this JCE");
- }
-
- if (log.isDebugEnabled()) {
- log.debug("Key encryption properties determined, decrypting key");
- }
- SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(encryptedKeyInfo.getAlgName());
- PBEKeySpec passwordSpec = new PBEKeySpec(getEncryptionPassword().toCharArray());
- SecretKey key = keyFactory.generateSecret(passwordSpec);
-
- Cipher cipher = Cipher.getInstance(encryptedKeyInfo.getAlgName());
- cipher.init(Cipher.DECRYPT_MODE, key, params);
- PKCS8EncodedKeySpec decrypted = encryptedKeyInfo.getKeySpec(cipher);
-
- if (log.isDebugEnabled()) {
- log.debug("Key decrypted, key format now non-encrypted PKCS8");
- }
-
- setEncrypted(false);
- setKeyBytes(decrypted.getEncoded());
-
- // Now that we've decrypted the key we've changed the ASN.1 structure
- // and so need to reread it.
- rootDerTag = (DERSequence) getRootDerTag(getKeyBytes());
-
- return getPkcs8Key();
-
- } catch (IOException e) {
- log.error("Invalid DER encoding for PKCS8 formatted encrypted key: " + e);
- throw new CredentialFactoryException("Unable to load private key; invalid key format.");
- } catch (InvalidKeySpecException e) {
- log.error("Incorrect password to unlock private key.", e);
- throw new CredentialFactoryException("Unable to load private key; incorrect key decryption password");
- } catch (GeneralSecurityException e) {
- log.error("JCE does not support algorithim to decrypt key: " + e);
- throw new CredentialFactoryException(
- "Unable to load private key; JCE does not support algorithim to decrypt key");
- }
- }
-
- /**
- * Gets the private key from a PKCS8 formatted key.
- *
- * @param bytes
- * the PKCS8 formatted key
- * @return the private key
- * @throws CredentialFactoryException
- * thrown is there is an error loading the private key
- */
- private PrivateKey getPkcs8Key() throws CredentialFactoryException {
-
- if (log.isDebugEnabled()) {
- log.debug("Reading unecrypted PKCS8 key to determine if key is RSA or DSA");
- }
- DERSequence childSeq = (DERSequence) rootDerTag.getObjectAt(1).getDERObject();
- DERObjectIdentifier derOID = (DERObjectIdentifier) childSeq.getObjectAt(0).getDERObject();
- String keyOID = derOID.getId();
-
- if (keyOID.equals(EncodedKey.RSAKey_OID)) {
- if (log.isDebugEnabled()) {
- log.debug("Found RSA key in PKCS8.");
- }
- return getRSAPkcs8DerKey();
- } else if (keyOID.equals(EncodedKey.DSAKey_OID)) {
- if (log.isDebugEnabled()) {
- log.debug("Found DSA key in PKCS8.");
- }
- return getDSAPkcs8DerKey();
- } else {
- log.error("Unexpected key type. Only RSA and DSA keys are supported in PKCS8 format.");
- throw new CredentialFactoryException("Unable to load private key; unexpected key type in PKCS8");
- }
- }
-
- /**
- * Gets a private key from a raw RSA PKCS8 formated DER encoded key.
- *
- * @param bytes
- * the encoded key
- * @return the private key
- * @throws CredentialFactoryException
- * thrown if the private key can not be read
- */
- private PrivateKey getRSAPkcs8DerKey() throws CredentialFactoryException {
-
- if (log.isDebugEnabled()) {
- log.debug("Constructing PrivateKey from PKCS8 encoded RSA key data");
- }
- try {
- KeyFactory keyFactory = KeyFactory.getInstance("RSA");
- PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(getKeyBytes());
- return keyFactory.generatePrivate(keySpec);
-
- } catch (Exception e) {
- log.error("Unable to load private key: " + e);
- throw new CredentialFactoryException("Unable to load private key.");
- }
- }
-
- /**
- * Gets a private key from a raw DSA PKCS8 formated DER encoded key.
- *
- * @param bytes
- * the encoded key
- * @return the private key
- * @throws CredentialFactoryException
- * thrown if the private key can not be read
- */
- private PrivateKey getDSAPkcs8DerKey() throws CredentialFactoryException {
-
- if (log.isDebugEnabled()) {
- log.debug("Constructing PrivateKey from PKCS8 encoded DSA key data");
- }
-
- try {
- KeyFactory keyFactory = KeyFactory.getInstance("DSA");
- PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(getKeyBytes());
- return keyFactory.generatePrivate(keySpec);
-
- } catch (Exception e) {
- log.error("Unable to load private key: " + e);
- throw new CredentialFactoryException("Unable to load private key.");
- }
- }
-
- /**
- * Converts a raw RSA key encoded in DER format into a private key object.
- *
- * @param key
- * the DER encoded key
- * @return the private key
- * @throws CredentialFactoryException
- * thrown if a key can not be constructed from the input
- */
- private PrivateKey getRSARawDerKey() throws CredentialFactoryException {
-
- if (log.isDebugEnabled()) {
- log.debug("Constructing PrivateKey from raw RSA key data");
- }
- try {
- RSAPrivateCrtKeySpec keySpec = new RSAPrivateCrtKeySpec(((DERInteger) rootDerTag.getObjectAt(1))
- .getValue(), ((DERInteger) rootDerTag.getObjectAt(2)).getValue(), ((DERInteger) rootDerTag
- .getObjectAt(3)).getValue(), ((DERInteger) rootDerTag.getObjectAt(4)).getValue(),
- ((DERInteger) rootDerTag.getObjectAt(5)).getValue(), ((DERInteger) rootDerTag.getObjectAt(6))
- .getValue(), ((DERInteger) rootDerTag.getObjectAt(7)).getValue(),
- ((DERInteger) rootDerTag.getObjectAt(8)).getValue());
-
- KeyFactory keyFactory = KeyFactory.getInstance("RSA");
-
- return keyFactory.generatePrivate(keySpec);
-
- } catch (GeneralSecurityException e) {
- log.error("Unable to marshall private key: " + e);
- throw new CredentialFactoryException("Unable to load private key.");
- }
- }
-
- /**
- * Converts a raw DSA key encoded in DER format into a private key object.
- *
- * @param derKey
- * DER encoded DSA key
- * @return the private key
- * @throws CredentialFactoryException
- * thrown if a key can not be constructed from the input
- */
- private PrivateKey getDSARawDerKey() throws CredentialFactoryException {
-
- if (log.isDebugEnabled()) {
- log.debug("Constructing PrivateKey from raw DSA key data");
- }
-
- try {
- DSAPrivateKeySpec keySpec = new DSAPrivateKeySpec(((DERInteger) rootDerTag.getObjectAt(5)).getValue(),
- ((DERInteger) rootDerTag.getObjectAt(1)).getValue(), ((DERInteger) rootDerTag.getObjectAt(2))
- .getValue(), ((DERInteger) rootDerTag.getObjectAt(3)).getValue());
-
- KeyFactory keyFactory = KeyFactory.getInstance("DSA");
-
- return keyFactory.generatePrivate(keySpec);
- } catch (GeneralSecurityException e) {
- log.error("Unable to marshall private key: " + e);
- throw new CredentialFactoryException("Unable to load private key.");
- }
- }
- }
-}
-
-/**
- * Loads a credential from a Java keystore.
- *
- * @author Walter Hoehn
- */
-
-class KeystoreCredentialResolver implements CredentialResolver {
-
- private static Logger log = Logger.getLogger(KeystoreCredentialResolver.class.getName());
-
- public Credential loadCredential(Element e) throws CredentialFactoryException {
-
- if (!e.getLocalName().equals("KeyStoreResolver")) {
- log.error("Invalid Credential Resolver configuration: expected <KeyStoreResolver> .");
- throw new CredentialFactoryException("Failed to initialize Credential Resolver.");
- }
-
- String keyStoreType = e.getAttribute("storeType");
- if (keyStoreType == null || keyStoreType.equals("")) {
- log.debug("Using default store type for credential.");
- keyStoreType = "JKS";
- }
-
- String path = loadPath(e);
- String alias = loadAlias(e);
- String certAlias = loadCertAlias(e, alias);
- String keyPassword = loadKeyPassword(e);
- String keyStorePassword = loadKeyStorePassword(e);
-
- try {
- KeyStore keyStore = KeyStore.getInstance(keyStoreType);
-
- keyStore.load(new ShibResource(path, this.getClass()).getInputStream(), keyStorePassword.toCharArray());
-
- PrivateKey privateKey = (PrivateKey) keyStore.getKey(alias, keyPassword.toCharArray());
-
- if (privateKey == null) { throw new CredentialFactoryException("No key entry was found with an alias of ("
- + alias + ")."); }
-
- Certificate[] certificates = keyStore.getCertificateChain(certAlias);
- if (certificates == null) { throw new CredentialFactoryException(
- "An error occurred while reading the java keystore: No certificate found with the specified alias ("
- + certAlias + ")."); }
-
- X509Certificate[] x509Certs = new X509Certificate[certificates.length];
- for (int i = 0; i < certificates.length; i++) {
- if (certificates[i] instanceof X509Certificate) {
- x509Certs[i] = (X509Certificate) certificates[i];
- } else {
- throw new CredentialFactoryException(
- "The KeyStore Credential Resolver can only load X509 certificates. Found an unsupported certificate of type ("
- + certificates[i] + ").");
- }
- }
-
- return new Credential(x509Certs, privateKey);
-
- } catch (KeyStoreException kse) {
- throw new CredentialFactoryException("An error occurred while accessing the java keystore: " + kse);
- } catch (NoSuchAlgorithmException nsae) {
- throw new CredentialFactoryException("Appropriate JCE provider not found in the java environment: " + nsae);
- } catch (CertificateException ce) {
- throw new CredentialFactoryException("The java keystore contained a certificate that could not be loaded: "
- + ce);
- } catch (IOException ioe) {
- throw new CredentialFactoryException("An error occurred while reading the java keystore: " + ioe);
- } catch (UnrecoverableKeyException uke) {
- throw new CredentialFactoryException(
- "An error occurred while attempting to load the key from the java keystore: " + uke);
- }
-
- }
-
- private String loadPath(Element e) throws CredentialFactoryException {
-
- NodeList pathElements = e.getElementsByTagNameNS(Credentials.credentialsNamespace, "Path");
- if (pathElements.getLength() < 1) {
- log.error("KeyStore path not specified.");
- throw new CredentialFactoryException("KeyStore Credential Resolver requires a <Path> specification.");
- }
- if (pathElements.getLength() > 1) {
- log.error("Multiple KeyStore 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("KeyStore path not specified.");
- throw new CredentialFactoryException("KeyStore Credential Resolver requires a <Path> specification.");
- }
- return path;
- }
-
- private String loadAlias(Element e) throws CredentialFactoryException {
-
- NodeList aliasElements = e.getElementsByTagNameNS(Credentials.credentialsNamespace, "KeyAlias");
- if (aliasElements.getLength() < 1) {
- log.error("KeyStore key alias not specified.");
- throw new CredentialFactoryException("KeyStore Credential Resolver requires an <KeyAlias> specification.");
- }
- if (aliasElements.getLength() > 1) {
- log.error("Multiple key alias specifications, using first.");
- }
- Node tnode = aliasElements.item(0).getFirstChild();
- String alias = null;
- if (tnode != null && tnode.getNodeType() == Node.TEXT_NODE) {
- alias = tnode.getNodeValue();
- }
- if (alias == null || alias.equals("")) {
- log.error("KeyStore key alias not specified.");
- throw new CredentialFactoryException("KeyStore Credential Resolver requires an <KeyAlias> specification.");
- }
- return alias;
- }
-
- private String loadCertAlias(Element e, String defaultAlias) throws CredentialFactoryException {
-
- NodeList aliasElements = e.getElementsByTagNameNS(Credentials.credentialsNamespace, "CertAlias");
- if (aliasElements.getLength() < 1) {
- log.debug("KeyStore cert alias not specified, defaulting to key alias.");
- return defaultAlias;
- }
-
- if (aliasElements.getLength() > 1) {
- log.error("Multiple cert alias specifications, using first.");
- }
-
- Node tnode = aliasElements.item(0).getFirstChild();
- String alias = null;
- if (tnode != null && tnode.getNodeType() == Node.TEXT_NODE) {
- alias = tnode.getNodeValue();
- }
- if (alias == null || alias.equals("")) {
- log.debug("KeyStore cert alias not specified, defaulting to key alias.");
- return defaultAlias;
- }
- return alias;
- }
-
- private String loadKeyStorePassword(Element e) throws CredentialFactoryException {
-
- NodeList passwordElements = e.getElementsByTagNameNS(Credentials.credentialsNamespace, "StorePassword");
- if (passwordElements.getLength() < 1) {
- log.error("KeyStore password not specified.");
- throw new CredentialFactoryException(
- "KeyStore Credential Resolver requires an <StorePassword> specification.");
- }
- if (passwordElements.getLength() > 1) {
- log.error("Multiple KeyStore password specifications, using first.");
- }
- Node tnode = passwordElements.item(0).getFirstChild();
- String password = null;
- if (tnode != null && tnode.getNodeType() == Node.TEXT_NODE) {
- password = tnode.getNodeValue();
- }
- if (password == null || password.equals("")) {
- log.error("KeyStore password not specified.");
- throw new CredentialFactoryException(
- "KeyStore Credential Resolver requires an <StorePassword> specification.");
- }
- return password;
- }
-
- private String loadKeyPassword(Element e) throws CredentialFactoryException {
-
- NodeList passwords = e.getElementsByTagNameNS(Credentials.credentialsNamespace, "KeyPassword");
- if (passwords.getLength() < 1) {
- log.error("KeyStore key password not specified.");
- throw new CredentialFactoryException(
- "KeyStore Credential Resolver requires an <KeyPassword> specification.");
- }
- if (passwords.getLength() > 1) {
- log.error("Multiple KeyStore key password specifications, using first.");
- }
- Node tnode = passwords.item(0).getFirstChild();
- String password = null;
- if (tnode != null && tnode.getNodeType() == Node.TEXT_NODE) {
- password = tnode.getNodeValue();
- }
- if (password == null || password.equals("")) {
- log.error("KeyStore key password not specified.");
- throw new CredentialFactoryException(
- "KeyStore Credential Resolver requires an <KeyPassword> specification.");
- }
- return password;
- }
-}
-
-/**
- * Uses implementation specified in the configuration to load a credential.
- *
- * @author Walter Hoehn
- */
-
-class CustomCredentialResolver implements CredentialResolver {
-
- private static Logger log = Logger.getLogger(CustomCredentialResolver.class.getName());
-
- public Credential loadCredential(Element e) throws CredentialFactoryException {
-
- if (!e.getLocalName().equals("CustomCredResolver")) {
- log.error("Invalid Credential Resolver configuration: expected <CustomCredResolver> .");
- throw new CredentialFactoryException("Failed to initialize Credential Resolver.");
- }
-
- String className = e.getAttribute("Class");
- if (className == null || className.equals("")) {
- log.error("Custom Credential Resolver requires specification of the attribute \"Class\".");
- throw new CredentialFactoryException("Failed to initialize Credential Resolver.");
- }
-
- try {
- return ((CredentialResolver) Class.forName(className).newInstance()).loadCredential(e);
-
- } catch (Exception loaderException) {
- log
- .error("Failed to load Custom Credential Resolver implementation class: "
- + loaderException.getMessage());
- throw new CredentialFactoryException("Failed to initialize Credential Resolver.");
- }
-
- }
-
-}
-
-class CredentialFactoryException extends Exception {
-
- CredentialFactoryException(String message) {
-
- super(message);
- }
-}
+++ /dev/null
-/*
- * Copyright [2005] [University Corporation for Advanced Internet Development, Inc.]
- *
- * Licensed 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 edu.internet2.middleware.shibboleth.common;
-
-/**
- * Defines a producer of SAML authentication and attribute assertions. A single instantiation of the Shibboleth IdP
- * software may represent more than one logical identity provider.
- *
- * @see ServiceProvider
- * @author Walter Hoehn
- */
-public interface IdentityProvider {
-
- /**
- * Returns the unique identifier for the indentity provider.
- *
- * @return the provider ID
- */
- public String getProviderId();
-
- /**
- * Returns the credential that this provider uses to sign SAML responses and assertions.
- *
- * @return the credential
- */
- public Credential getSigningCredential();
-
-}
\ No newline at end of file
+++ /dev/null
-/*
- * Copyright [2005] [University Corporation for Advanced Internet Development, Inc.]
- *
- * Licensed 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 edu.internet2.middleware.shibboleth.common;
-
-import javax.xml.namespace.QName;
-
-/**
- * @author Walter Hoehn
- */
-public class InvalidNameIdentifierException extends NameIdentifierMappingException {
-
- QName[] errorCodes;
-
- public InvalidNameIdentifierException(String message, QName[] errorCodes) {
-
- super(message);
- this.errorCodes = errorCodes;
- }
-
- public QName[] getSAMLErrorCodes() {
-
- return errorCodes;
- }
-}
+++ /dev/null
-/*
- * Copyright [2005] [University Corporation for Advanced Internet Development, Inc.]
- *
- * Licensed 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 edu.internet2.middleware.shibboleth.common;
-
-import java.io.Serializable;
-import java.security.Principal;
-
-/**
- * Shibboleth basic <code>Principal</code> ipmlementation for internal use.
- *
- * @author Walter Hoehn (wassa@columbia.edu)
- */
-
-public class LocalPrincipal implements Principal, Serializable {
-
- static final long serialVersionUID = 1L;
- private String principalName;
-
- /**
- * Constructor for LocalPrincipal.
- */
-
- public LocalPrincipal(String principalName) {
-
- this.principalName = principalName;
- }
-
- /**
- * @see java.security.Principal#getName()
- */
-
- public String getName() {
-
- return principalName;
- }
-
- /**
- * @see java.lang.Object#equals(Object)
- */
- public boolean equals(Object obj) {
-
- if (!(obj instanceof LocalPrincipal)) { return false; }
- return ((LocalPrincipal) obj).getName().equals(getName());
- }
-
- /**
- * @see java.lang.Object#hashCode()
- */
- public int hashCode() {
-
- return "LocalPrincipal".hashCode() + principalName.hashCode();
- }
-
-}
+++ /dev/null
-/*
- * Copyright [2005] [University Corporation for Advanced Internet Development, Inc.]
- *
- * Licensed 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 edu.internet2.middleware.shibboleth.common;
-
-import java.net.URI;
-import java.security.Principal;
-
-import org.opensaml.SAMLNameIdentifier;
-
-/**
- * Defines a mechanism for converting back and forth between SAML Name Identifiers and local {@link LocalPrincipal}
- * objects.
- *
- * @author Walter Hoehn
- */
-public interface NameIdentifierMapping {
-
- public static final String mappingNamespace = "urn:mace:shibboleth:namemapper:1.0";
-
- /**
- * @return the id of this mapping or <code>null</code> is it is not configured with one
- */
- public String getId();
-
- /**
- * Returns the Name Identifier format for this mapping.
- *
- * @return the format
- */
- public URI getNameIdentifierFormat();
-
- /**
- * Maps a SAML Name Identifier to a local principal using the appropriate registered mapping. Must ensure that the
- * SAML NameIdentifer is properly qualified.
- *
- * @param nameId
- * the SAML Name Identifier that should be converted
- * @param sProv
- * the provider initiating the request
- * @param idProv
- * the provider handling the request
- * @return the local principal
- * @throws NameIdentifierMappingException
- * If the {@link NameMapper}encounters an internal error
- * @throws InvalidNameIdentifierException
- * If the {@link SAMLNameIdentifier}contains invalid data
- */
- public Principal getPrincipal(SAMLNameIdentifier nameId, ServiceProvider sProv, IdentityProvider idProv)
- throws NameIdentifierMappingException, InvalidNameIdentifierException;
-
- /**
- * Maps a local principal to a SAML Name Identifier.
- *
- * @param principal
- * the principal to map
- * @param sProv
- * the provider initiating the request
- * @param idProv
- * the provider handling the request
- * @return the SAML name identifier
- * @throws NameIdentifierMappingException
- * If the {@link NameMapper}encounters an internal error
- */
- public SAMLNameIdentifier getNameIdentifier(LocalPrincipal principal, ServiceProvider sProv, IdentityProvider idProv)
- throws NameIdentifierMappingException;
-
- /**
- * Cleanup resources that won't be released when this object is garbage-collected
- */
- public void destroy();
-
-}
\ No newline at end of file
+++ /dev/null
-/*
- * Copyright [2005] [University Corporation for Advanced Internet Development, Inc.]
- *
- * Licensed 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 edu.internet2.middleware.shibboleth.common;
-
-/**
- * Indicates an error occurred while manipulating an instance of <code>NameIdentifierMapping</code>
- *
- * @author Walter Hoehn
- */
-public class NameIdentifierMappingException extends Exception {
-
- public NameIdentifierMappingException(String message) {
-
- super(message);
- }
-}
+++ /dev/null
-/*
- * Copyright [2005] [University Corporation for Advanced Internet Development, Inc.]
- *
- * Licensed 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 edu.internet2.middleware.shibboleth.common;
-
-/**
- * Defines a configuration relationship between service providers and an identity provider. In Shibboleth parlance, a
- * relying party represents a SP or group of SPs (perhaps a federation).
- *
- * @author Walter Hoehn
- */
-public interface RelyingParty {
-
- /**
- * Returns the appropriate identity provider to create assertions for this relying party.
- *
- * @return the identity provider
- */
- public IdentityProvider getIdentityProvider();
-
- /**
- * A boolean indication of whether internal errors should be transmitted to this {@link RelyingParty}
- */
- public boolean passThruErrors();
-
- /**
- * A boolean indication of whether attributes should be pushed without regard for the profile (POST vs. Artifact).
- * This should be be mutually exclusive with forceAttributeNoPush().
- */
- public boolean forceAttributePush();
-
- /**
- * A boolean indication of whether attributes should be NOT pushed without regard for the profile (POST vs.
- * Artifact).
- */
- public boolean forceAttributeNoPush();
-
- /**
- * A boolean indication of whether the default SSO browser profile should be POST or Artifact. "true" indicates POST
- * and "false" indicates Artifact.
- */
- public boolean defaultToPOSTProfile();
-
- /**
- * A boolean indication of whether assertions issued to this Relying Party should be digitally signed (This is in
- * addition to profile-specific signing).
- */
- public boolean wantsAssertionsSigned();
-
- /**
- * A boolean indication of whether attributes sent with an authentication response should be included in the same
- * assertion or left in a second assertion for compatibility with broken SAML products.
- */
- public boolean singleAssertion();
-
- /**
- * Returns the type of SAML Artifact that this appropriate for use with this Relying Party.
- */
- public int getPreferredArtifactType();
-
- /**
- * Returns the default "TARGET" attribute to be used with the artifact profile or null if none is specified.
- */
- public String getDefaultTarget();
-
- /**
- * Provides a mechanism for extension developers to pass relying party specific data into their extensions.
- */
- public String getCustomAttribute(String name);
-
-}
+++ /dev/null
-/*
- * Copyright [2005] [University Corporation for Advanced Internet Development, Inc.]
- *
- * Licensed 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 edu.internet2.middleware.shibboleth.common;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.apache.log4j.Logger;
-import org.opensaml.saml2.metadata.EntitiesDescriptor;
-import org.opensaml.saml2.metadata.EntityDescriptor;
-import org.opensaml.saml2.metadata.provider.MetadataProvider;
-import org.opensaml.saml2.metadata.provider.MetadataProviderException;
-import org.opensaml.xml.XMLObject;
-import org.w3c.dom.Attr;
-import org.w3c.dom.Element;
-import org.w3c.dom.NamedNodeMap;
-import org.w3c.dom.NodeList;
-
-import edu.internet2.middleware.shibboleth.idp.IdPConfig;
-
-/**
- * Class for determining the effective relying party from the unique id of the service provider. Checks first for an
- * exact match on the service provider, then for membership in a group of providers (perhaps a federation). Uses the
- * default relying party if neither is found.
- *
- * @author Walter Hoehn
- */
-public class RelyingPartyMapper {
-
- private static Logger log = Logger.getLogger(RelyingPartyMapper.class.getName());
- protected Map<String, NamedRelyingParty> relyingParties = new HashMap<String, NamedRelyingParty>();
- protected RelyingParty defaultRelyingParty;
- protected RelyingParty anonymousRelyingParty;
-
- private MetadataProvider metaData;
- private Credentials credentials;
-
- public RelyingPartyMapper(Element rawConfig, Credentials credentials) throws RelyingPartyMapperException {
-
- if (credentials == null) { throw new IllegalArgumentException(
- "RelyingPartyMapper cannot be started without proper access to the IdP configuration."); }
-
- this.credentials = credentials;
-
- // Load specified <RelyingParty/> elements
- NodeList itemElements = rawConfig.getElementsByTagNameNS(IdPConfig.configNameSpace, "RelyingParty");
- for (int i = 0; i < itemElements.getLength(); i++) {
- addRelyingParty((Element) itemElements.item(i));
- }
-
- // Load <AnonymousRelyingParty/> element, if specified
- itemElements = rawConfig.getElementsByTagNameNS(IdPConfig.configNameSpace, "AnonymousRelyingParty");
- if (itemElements.getLength() > 1) {
- log.error("Found multiple <AnonymousRelyingParty/> elements. Ignoring all but the first...");
- }
- if (itemElements.getLength() < 1) {
- log.error("No <AnonymousRelyingParty/> elements found. Disabling support for responding "
- + "to anonymous relying parties.");
- } else {
- addAnonymousRelyingParty((Element) itemElements.item(0));
- }
-
- // Load <DefaultRelyingParty/> element, if specified
- itemElements = rawConfig.getElementsByTagNameNS(IdPConfig.configNameSpace, "DefaultRelyingParty");
- if (itemElements.getLength() > 1) {
- log.error("Found multiple <DefaultRelyingParty/> elements. Ignoring all but the first...");
- }
- if (itemElements.getLength() < 1) {
- log.error("No <DefaultRelyingParty/> elements found. Disabling support for responding "
- + "to anonymous relying parties.");
- } else {
- addDefaultRelyingParty((Element) itemElements.item(0));
- }
- }
-
- public boolean anonymousSuported() {
-
- return (anonymousRelyingParty != null);
- }
-
- public RelyingParty getAnonymousRelyingParty() {
-
- return anonymousRelyingParty;
-
- }
-
- public void setMetadata(MetadataProvider metadata) {
-
- this.metaData = metadata;
- }
-
- private NamedRelyingParty findRelyingPartyByGroup(String providerIdFromSP) {
-
- if (metaData == null) { return null; }
-
- // Attempt to lookup the entity in the metdata
- EntityDescriptor provider = null;
- try {
- provider = metaData.getEntityDescriptor(providerIdFromSP);
- } catch (MetadataProviderException e) {
- log.error("Problem encountered during metadata lookup of entity (" + providerIdFromSP + "): " + e);
- }
-
- // OK, if we found it travel recurse down the tree of parent entities
- if (provider != null) {
- EntitiesDescriptor parent = getParentEntitiesDescriptor(provider);
-
- while (parent != null) {
- if (parent.getName() != null) {
- if (relyingParties.containsKey(parent.getName())) {
- log.info("Found matching Relying Party for group (" + parent.getName() + ").");
- return (NamedRelyingParty) relyingParties.get(parent.getName());
- } else {
- log.debug("Provider is a member of group (" + parent.getName()
- + "), but no matching Relying Party was found.");
- }
- }
- parent = getParentEntitiesDescriptor(parent);
- }
- }
- return null;
- }
-
- /**
- * Returns the appropriate relying party for the supplied service provider id.
- */
- public RelyingParty getRelyingParty(String providerIdFromSP) {
-
- if (providerIdFromSP == null || providerIdFromSP.equals("")) { throw new IllegalArgumentException(
- "Incorrect use of ServiceProviderMapper. Cannot lookup relying party without a provider ID."); }
-
- // Look for a configuration for the specific relying party
- if (relyingParties.containsKey(providerIdFromSP)) {
- log.info("Found Relying Party for (" + providerIdFromSP + ").");
- return (RelyingParty) relyingParties.get(providerIdFromSP);
- }
-
- // Lookup by group
- // Next, check to see if the relying party is in any groups
- NamedRelyingParty groupParty = findRelyingPartyByGroup(providerIdFromSP);
- if (groupParty != null) {
- log.info("Provider is a member of Relying Party (" + groupParty.getName() + ").");
- return groupParty;
- }
-
- // Use default if we have one
- if (defaultRelyingParty != null) {
- log.debug("No matching relying party found. Using default relying party.");
- return defaultRelyingParty;
- }
-
- // Alright, there's nothing available to us
- return null;
-
- }
-
- private void addRelyingParty(Element e) throws RelyingPartyMapperException {
-
- log.debug("Found a Relying Party configuration element.");
- try {
- if (e.getLocalName().equals("RelyingParty")) {
- NamedRelyingParty party = new NamedRelyingParty(e, credentials);
- log.debug("Relying Party (" + party.getName() + ") loaded.");
- relyingParties.put(party.getName(), party);
- }
- } catch (RelyingPartyMapperException exc) {
- log.error("Encountered an error while attempting to load Relying Party configuration. Skipping...");
- }
- }
-
- private void addAnonymousRelyingParty(Element e) throws RelyingPartyMapperException {
-
- log.debug("Found an Anonymous Relying Party configuration element.");
- try {
- if (e.getLocalName().equals("AnonymousRelyingParty")) {
- RelyingParty party = new RelyingPartyImpl(e, credentials);
- log.debug("Anonymous Relying Party loaded.");
- anonymousRelyingParty = party;
- }
- } catch (RelyingPartyMapperException exc) {
- log.error("Encountered an error while attempting to load Anonymous Relying"
- + " Party configuration. Skipping...");
- }
- }
-
- private void addDefaultRelyingParty(Element e) throws RelyingPartyMapperException {
-
- log.debug("Found a Default Relying Party configuration element.");
- try {
- if (e.getLocalName().equals("DefaultRelyingParty")) {
- RelyingParty party = new RelyingPartyImpl(e, credentials);
- log.debug("Default Relying Party loaded.");
- defaultRelyingParty = party;
- }
- } catch (RelyingPartyMapperException exc) {
- log.error("Encountered an error while attempting to load Default "
- + "Relying Party configuration. Skipping...");
- }
- }
-
- private EntitiesDescriptor getParentEntitiesDescriptor(XMLObject entity) {
-
- Object parent = entity.getParent();
-
- if (parent instanceof EntitiesDescriptor) { return (EntitiesDescriptor) parent; }
-
- return null;
- }
-
- /**
- * Base relying party implementation.
- *
- * @author Walter Hoehn
- */
- protected class RelyingPartyImpl implements RelyingParty {
-
- private RelyingPartyIdentityProvider identityProvider;
- private String providerId;
- private boolean passThruErrors = false;
- private boolean forceAttributePush = false;
- private boolean forceAttributeNoPush = false;
- private boolean singleAssertion = false;
- private boolean defaultToPOST = true;
- private boolean wantsAssertionsSigned = false;
- private int preferredArtifactType = 1;
- private String defaultTarget;
- private Map<String, String> extensionAttributes = new HashMap<String, String>();
- private Collection<String> knownAttributes = Arrays.asList(new String[]{"providerId", "passThruErrors",
- "defaultToPOSTProfile", "singleAssertion", "signAssertions", "defaultTarget", "forceAttributePush",
- "preferredArtifactType", "signingCredential"});
-
- public RelyingPartyImpl(Element partyConfig, Credentials credentials) throws RelyingPartyMapperException {
-
- // Process overrides for global configuration data
- String attribute = ((Element) partyConfig).getAttribute("providerId");
- if (attribute == null || attribute.equals("")) {
- log.error("Relying Party providerId not set. Add a (providerId) " + "attribute to <RelyingParty>.");
- throw new RelyingPartyMapperException("Required configuration not specified.");
- }
- providerId = attribute;
- log.debug("Setting providerId for Relying Party to (" + attribute + ").");
-
- attribute = ((Element) partyConfig).getAttribute("passThruErrors");
- if (attribute != null && !attribute.equals("")) {
- log.debug("Setting passThruErrors for Relying Pary with (" + attribute + ").");
- passThruErrors = Boolean.valueOf(attribute).booleanValue();
- }
-
- // SSO profile defaulting
- attribute = ((Element) partyConfig).getAttribute("defaultToPOSTProfile");
- if (attribute != null && !attribute.equals("")) {
- defaultToPOST = Boolean.valueOf(attribute).booleanValue();
- }
- if (defaultToPOST) {
- log.debug("Relying party defaults to POST profile.");
- } else {
- log.debug("Relying party defaults to Artifact profile.");
- }
-
- attribute = ((Element) partyConfig).getAttribute("singleAssertion");
- if (attribute != null && !attribute.equals("")) {
- singleAssertion = Boolean.valueOf(attribute).booleanValue();
- }
- if (singleAssertion) {
- log.debug("Relying party defaults to a single assertion when pushing attributes.");
- } else {
- log.debug("Relying party defaults to multiple assertions when pushing attributes.");
- }
-
- // Relying Party wants assertions signed?
- attribute = ((Element) partyConfig).getAttribute("signAssertions");
- if (attribute != null && !attribute.equals("")) {
- wantsAssertionsSigned = Boolean.valueOf(attribute).booleanValue();
- }
- if (wantsAssertionsSigned) {
- log.debug("Relying party wants SAML Assertions to be signed.");
- } else {
- log.debug("Relying party does not want SAML Assertions to be signed.");
- }
-
- // Set a default target for use in artifact redirects
- defaultTarget = ((Element) partyConfig).getAttribute("defaultTarget");
-
- // Determine whether or not we are forcing attribute push on or off
- String forcePush = ((Element) partyConfig).getAttribute("forceAttributePush");
- String forceNoPush = ((Element) partyConfig).getAttribute("forceAttributeNoPush");
-
- if (forcePush != null && Boolean.valueOf(forcePush).booleanValue() && forceNoPush != null
- && Boolean.valueOf(forceNoPush).booleanValue()) {
- log.error("Invalid configuration: Attribute push is forced to ON and OFF for this relying "
- + "party. Turning off forcing in favor of profile defaults.");
- } else {
- forceAttributePush = Boolean.valueOf(forcePush).booleanValue();
- forceAttributeNoPush = Boolean.valueOf(forceNoPush).booleanValue();
- log.debug("Attribute push forcing is set to (" + forceAttributePush + ").");
- log.debug("No attribute push forcing is set to (" + forceAttributeNoPush + ").");
- }
-
- attribute = ((Element) partyConfig).getAttribute("preferredArtifactType");
- if (attribute != null && !attribute.equals("")) {
- log.debug("Overriding preferredArtifactType for Relying Pary with (" + attribute + ").");
- try {
- preferredArtifactType = Integer.parseInt(attribute);
- } catch (NumberFormatException e) {
- log.error("(preferredArtifactType) attribute to is not a valid integer.");
- throw new RelyingPartyMapperException("Configuration is invalid.");
- }
- log.debug("Preferred artifact type: (" + preferredArtifactType + ").");
- }
-
- // Load the credential for signing
- String credentialName = ((Element) partyConfig).getAttribute("signingCredential");
- Credential signingCredential = credentials.getCredential(credentialName);
- if (signingCredential == null) {
- if (credentialName == null || credentialName.equals("")) {
- log.error("Relying Party credential not set. Add a (signingCredential) "
- + "attribute to <RelyingParty>.");
- throw new RelyingPartyMapperException("Required configuration not specified.");
- } else {
- log.error("Relying Party credential invalid. Fix the (signingCredential) attribute "
- + "on <RelyingParty>.");
- throw new RelyingPartyMapperException("Required configuration is invalid.");
- }
-
- }
-
- // Initialize and Identity Provider object for this use by this relying party
- identityProvider = new RelyingPartyIdentityProvider(providerId, signingCredential);
-
- // Track extension attributes
- NamedNodeMap nodeMap = ((Element) partyConfig).getAttributes();
- for (int i = 0; i < nodeMap.getLength(); i++) {
- Attr attr = (Attr) nodeMap.item(i);
- if (!knownAttributes.contains(attr.getName())) {
- extensionAttributes.put(attr.getName(), attr.getValue());
- }
- }
- }
-
- public IdentityProvider getIdentityProvider() {
-
- return identityProvider;
- }
-
- public boolean passThruErrors() {
-
- return passThruErrors;
- }
-
- public boolean forceAttributePush() {
-
- return forceAttributePush;
- }
-
- public boolean forceAttributeNoPush() {
-
- return forceAttributeNoPush;
- }
-
- public boolean singleAssertion() {
-
- return singleAssertion;
- }
-
- public boolean defaultToPOSTProfile() {
-
- return defaultToPOST;
- }
-
- public boolean wantsAssertionsSigned() {
-
- return wantsAssertionsSigned;
- }
-
- public int getPreferredArtifactType() {
-
- return preferredArtifactType;
- }
-
- public String getDefaultTarget() {
-
- return defaultTarget;
- }
-
- public String getCustomAttribute(String name) {
-
- return extensionAttributes.get(name);
- }
-
- /**
- * Default identity provider implementation.
- *
- * @author Walter Hoehn
- */
- protected class RelyingPartyIdentityProvider implements IdentityProvider {
-
- private String providerId;
- private Credential credential;
-
- public RelyingPartyIdentityProvider(String providerId, Credential credential) {
-
- this.providerId = providerId;
- this.credential = credential;
- }
-
- /*
- * @see edu.internet2.middleware.shibboleth.common.IdentityProvider#getProviderId()
- */
- public String getProviderId() {
-
- return providerId;
- }
-
- /*
- * @see edu.internet2.middleware.shibboleth.common.IdentityProvider#getSigningCredential()
- */
- public Credential getSigningCredential() {
-
- return credential;
- }
- }
-
- }
-
- class NamedRelyingParty extends RelyingPartyImpl {
-
- private String name;
-
- public NamedRelyingParty(Element partyConfig, Credentials credentials) throws RelyingPartyMapperException {
-
- super(partyConfig, credentials);
- // Get party name
- name = ((Element) partyConfig).getAttribute("name");
- if (name == null || name.equals("")) {
- log.error("Relying Party name not set. Add a (name) attribute to <RelyingParty>.");
- throw new RelyingPartyMapperException("Required configuration not specified.");
- }
- log.debug("Loading Relying Party: (" + name + ").");
- }
-
- public String getName() {
-
- return name;
- }
- }
-}
\ No newline at end of file
+++ /dev/null
-/*
- * Copyright [2005] [University Corporation for Advanced Internet Development, Inc.]
- *
- * Licensed 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 edu.internet2.middleware.shibboleth.common;
-
-/**
- * @author Walter Hoehn
- */
-public class RelyingPartyMapperException extends Exception {
-
- public RelyingPartyMapperException(String message) {
-
- super(message);
- }
-
-}
+++ /dev/null
-/*
- * Copyright [2005] [University Corporation for Advanced Internet Development, Inc.]
- *
- * Licensed 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 edu.internet2.middleware.shibboleth.common;
-
-/**
- * Defines a consumer of SAML assertions.
- *
- * @see IdentityProvider
- * @author Walter Hoehn
- */
-public interface ServiceProvider extends RelyingParty {
-
- /**
- * Returns the unique identifier for the service provider.
- *
- * @return the provider ID
- */
- public String getProviderId();
-}
\ No newline at end of file
+++ /dev/null
-/*
- * Copyright [2005] [University Corporation for Advanced Internet Development, Inc.]
- *
- * Licensed 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 edu.internet2.middleware.shibboleth.common;
-
-/**
- * Signals that the a Shibboleth component has been given insufficient or improper runtime configuration paramerts.
- *
- * @author Walter Hoehn (wassa@columbia.edu)
- */
-public class ShibbolethConfigurationException extends Exception {
-
- public ShibbolethConfigurationException(String message) {
- super(message);
- }
-
- public ShibbolethConfigurationException(String message, Throwable t) {
- super(message,t);
- }
-}
+++ /dev/null
-/*
- * Copyright [2005] [University Corporation for Advanced Internet Development, Inc.]
- *
- * Licensed 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 edu.internet2.middleware.shibboleth.common;
-
-/**
- * Utility class for XML constants
- *
- * @author Scott Cantor
- * @created January 2, 2002
- */
-public class XML {
-
- /** SAMLv2 Metadata XML namespace */
- public final static String SAML2META_NS = "urn:oasis:names:tc:SAML:2.0:metadata";
-
- /** SAMLv2 Metadata Extension XML namespace */
- public final static String SAML2METAEXT_NS = "urn:oasis:names:tc:SAML:metadata:extension";
-
- /** SAMLv2 Assertion XML namespace */
- public final static String SAML2ASSERT_NS = "urn:oasis:names:tc:SAML:2.0:assertion";
-
- /** Shibboleth XML namespace */
- public final static String SHIB_NS = "urn:mace:shibboleth:1.0";
-
- /** Shibboleth Metadata XML namespace */
- public final static String SHIBMETA_NS = "urn:mace:shibboleth:metadata:1.0";
-
- /** Shibboleth trust metadata XML namespace */
- public final static String TRUST_NS = "urn:mace:shibboleth:trust:1.0";
-
- /** XML Encryption namespace */
- public final static String XMLENC_NS = "http://www.w3.org/2001/04/xmlenc#";
-
- public final static String MAIN_SHEMA_ID = "shibboleth-targetconfig-1.0.xsd";
- public final static String IDP_SHEMA_ID = "shibboleth-idpconfig-1.0.xsd";
-}
+++ /dev/null
-/*
- * Copyright [2005] [University Corporation for Advanced Internet Development, Inc.]
- *
- * Licensed 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 edu.internet2.middleware.shibboleth.common.provider;
-
-import java.io.Serializable;
-
-import org.apache.log4j.Logger;
-import javax.xml.namespace.QName;
-import org.opensaml.SAMLException;
-import org.w3c.dom.Element;
-
-import edu.internet2.middleware.shibboleth.common.LocalPrincipal;
-import edu.internet2.middleware.shibboleth.common.NameIdentifierMappingException;
-
-/**
- * Base class for {@link NameIdentifierMapping}implementations that support Shibboleth Attribute Query Handles.
- *
- * @author Walter Hoehn
- */
-public abstract class AQHNameIdentifierMapping extends BaseNameIdentifierMapping {
-
- private static Logger log = Logger.getLogger(AQHNameIdentifierMapping.class.getName());
- /** Time in seconds for which handles are valid */
- protected long handleTTL = 1800;
- protected static QName[] errorCodes = {SAMLException.REQUESTER,
- new QName(edu.internet2.middleware.shibboleth.common.XML.SHIB_NS, "InvalidHandle")};
-
- public AQHNameIdentifierMapping(Element config) throws NameIdentifierMappingException {
-
- super(config);
-
- String rawTTL = ((Element) config).getAttribute("handleTTL");
- try {
- if (rawTTL != null && !rawTTL.equals("")) {
- handleTTL = Long.parseLong(rawTTL);
- if (handleTTL < 30) {
- log.warn("You have set the Attribute Query Handle \"Time To Live\' to a very low "
- + "value. It is recommended that you increase it.");
- }
- }
- log.debug("Attribute Query Handle TTL set to (" + handleTTL + ") seconds.");
-
- } catch (NumberFormatException nfe) {
- log.error("Value for attribute \"handleTTL\" mus be a long integer.");
- throw new NameIdentifierMappingException("Could not load Name Identifier Mapping with configured data.");
- }
- }
-
- protected HandleEntry createHandleEntry(LocalPrincipal principal) {
-
- return new HandleEntry(principal, handleTTL);
- }
-}
-
-class HandleEntry implements Serializable {
-
- static final long serialVersionUID = 1L;
- protected LocalPrincipal principal;
- protected long expirationTime;
-
- /**
- * Creates a HandleEntry
- *
- * @param principal
- * the principal represented by this entry.
- * @param TTL
- * the time, in seconds, for which the handle should be valid.
- */
- protected HandleEntry(LocalPrincipal principal, long TTL) {
-
- this.principal = principal;
- expirationTime = System.currentTimeMillis() + (TTL * 1000);
- }
-
- protected boolean isExpired() {
-
- return (System.currentTimeMillis() >= expirationTime);
- }
-
- public long getExpirationTime() {
-
- return expirationTime;
- }
-
- public void setExpirationTime(long expr) {
-
- expirationTime = expr;
- }
-}
\ No newline at end of file
+++ /dev/null
-/*
- * Copyright [2005] [University Corporation for Advanced Internet Development, Inc.]
- *
- * Licensed 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 edu.internet2.middleware.shibboleth.common.provider;
-
-import java.util.Date;
-
-import edu.internet2.middleware.shibboleth.common.Cache;
-
-/**
- * Functionality common to all implementations of <code>Cache</code>.
- *
- * @author Walter Hoehn
- */
-public abstract class BaseCache implements Cache {
-
- private String name;
- private CacheType cacheType;
-
- protected BaseCache(String name, CacheType type) {
-
- if (name == null || type == null) { throw new IllegalArgumentException(
- "Name and type are required for construction of BaseCache."); }
-
- this.name = name;
- this.cacheType = type;
- }
-
- public CacheType getCacheType() {
-
- return cacheType;
- }
-
- public String getName() {
-
- return name;
- }
-
- protected class CacheEntry {
-
- protected Date expiration;
- protected String value;
-
- protected CacheEntry(String value, long duration) {
-
- this.value = value;
- expiration = new Date(System.currentTimeMillis() + (duration * 1000));
- }
-
- protected CacheEntry(String value, Date expireAt) {
-
- this.value = value;
- this.expiration = expireAt;
- }
-
- protected boolean isExpired() {
-
- return (new Date().after(expiration));
- }
- }
-}
+++ /dev/null
-/*
- * Copyright [2005] [University Corporation for Advanced Internet Development, Inc.]
- *
- * Licensed 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 edu.internet2.middleware.shibboleth.common.provider;
-
-import java.net.URI;
-import java.net.URISyntaxException;
-
-import org.apache.log4j.Logger;
-import org.opensaml.SAMLNameIdentifier;
-import org.w3c.dom.Element;
-
-import edu.internet2.middleware.shibboleth.common.IdentityProvider;
-import edu.internet2.middleware.shibboleth.common.NameIdentifierMapping;
-import edu.internet2.middleware.shibboleth.common.NameIdentifierMappingException;
-
-/**
- * Base class for processing name identifier mapping configuration.
- *
- * @author Walter Hoehn
- */
-public abstract class BaseNameIdentifierMapping implements NameIdentifierMapping {
-
- private static Logger log = Logger.getLogger(BaseNameIdentifierMapping.class.getName());
- private URI format;
- private String id;
-
- public BaseNameIdentifierMapping(Element config) throws NameIdentifierMappingException {
-
- if (!config.getLocalName().equals("NameMapping")) { throw new IllegalArgumentException(); }
-
- String rawFormat = ((Element) config).getAttribute("format");
- if (rawFormat == null || rawFormat.equals("")) {
- log.error("Name Mapping requires a \"format\" attribute.");
- throw new NameIdentifierMappingException("Invalid mapping information specified.");
- }
-
- try {
- format = new URI(rawFormat);
- } catch (URISyntaxException e) {
- log.error("Name Mapping attribute \"format\" is not a valid URI: " + e);
- throw new NameIdentifierMappingException("Invalid mapping information specified.");
- }
-
- String id = ((Element) config).getAttribute("id");
- if (id != null && !id.equals("")) {
- this.id = id;
- }
-
- }
-
- public URI getNameIdentifierFormat() {
-
- return format;
- }
-
- public String getId() {
-
- return id;
- }
-
- public void destroy() {
-
- // nothing to do
- }
-
- protected void verifyQualifier(SAMLNameIdentifier nameId, IdentityProvider idProv)
- throws NameIdentifierMappingException {
-
- if (idProv.getProviderId() == null || !idProv.getProviderId().equals(nameId.getNameQualifier())) {
- log.error("The name qualifier (" + nameId.getNameQualifier()
- + ") for the referenced subject is not valid for this identity provider.");
- throw new NameIdentifierMappingException("The name qualifier (" + nameId.getNameQualifier()
- + ") for the referenced subject is not valid for this identity provider.");
- }
- }
-}
\ No newline at end of file
+++ /dev/null
-/*
- * Copyright [2005] [University Corporation for Advanced Internet Development, Inc.]
- *
- * Licensed 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 edu.internet2.middleware.shibboleth.common.provider;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
-import java.io.StringReader;
-import java.io.StringWriter;
-import java.security.GeneralSecurityException;
-import java.security.SecureRandom;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.zip.GZIPInputStream;
-import java.util.zip.GZIPOutputStream;
-
-import javax.crypto.Cipher;
-import javax.crypto.Mac;
-import javax.crypto.SecretKey;
-import javax.crypto.spec.IvParameterSpec;
-import javax.servlet.http.Cookie;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.transform.OutputKeys;
-import javax.xml.transform.Transformer;
-import javax.xml.transform.TransformerFactory;
-import javax.xml.transform.dom.DOMSource;
-import javax.xml.transform.stream.StreamResult;
-
-import org.apache.log4j.Logger;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.NodeList;
-import org.xml.sax.InputSource;
-
-import edu.internet2.middleware.shibboleth.common.Cache;
-import edu.internet2.middleware.shibboleth.common.CacheException;
-import edu.internet2.middleware.shibboleth.utils.Base32;
-
-/**
- * <code>Cache</code> implementation that uses browser cookies to store data. Symmetric and HMAC algorithms are used
- * to encrypt and verify the data. Due to the size limitations of cookie storage, data may interleaved among multiple
- * cookies. NOTE: Using this cache implementation in a standalon tomcat configuration will usually require that the
- * "maxHttpHeaderSize" parameter be greatly increased.
- *
- * @author Walter Hoehn
- */
-public class CookieCache extends BaseCache implements Cache {
-
- private static Logger log = Logger.getLogger(CookieCache.class.getName());
- private HttpServletResponse response;
- private Collection<Cookie> myCurrentCookies = new ArrayList<Cookie>();
- private Map<String, CacheEntry> dataCache = new HashMap<String, CacheEntry>();
- private static final int CHUNK_SIZE = 4 * 1024; // minimal browser requirement
- private static final int COOKIE_LIMIT = 20; // minimal browser requirement
- private static final String NAME_PREFIX = "IDP_CACHE:";
- private static int totalCookies = 0;
- protected SecretKey secret;
- private static SecureRandom random = new SecureRandom();
- private String cipherAlgorithm;
- private String macAlgorithm;
-
- public CookieCache(String name, SecretKey key, String cipherAlgorithm, String macAlgorithm,
- HttpServletRequest request, HttpServletResponse response) throws CacheException {
-
- super(name, Cache.CacheType.CLIENT_SIDE);
- this.secret = key;
- this.cipherAlgorithm = cipherAlgorithm;
- this.macAlgorithm = macAlgorithm;
- this.response = response;
- Cookie[] requestCookies = request.getCookies();
- if (requestCookies != null) {
- for (int i = 0; i < requestCookies.length; i++) {
- if (requestCookies[i].getName().startsWith(NAME_PREFIX + getName())
- && requestCookies[i].getValue() != null) {
- myCurrentCookies.add(requestCookies[i]);
- }
- }
- }
-
- if (usingDefaultSecret()) {
- log.warn("You are running the Cookie Cache with the "
- + "default secret key. This is UNSAFE! Please change "
- + "this configuration and restart the IdP.");
- }
-
- initFromCookies();
- }
-
- public void postProcessing() throws CacheException {
-
- if (totalCookies > (COOKIE_LIMIT - 1)) {
- log.warn("The Cookie Cache mechanism is about to write a large amount of data to the "
- + "client. This may not work with some browser software, so it is recommended"
- + " that you investigate other caching mechanisms.");
- }
-
- flushCache();
- }
-
- public boolean contains(String key) throws CacheException {
-
- CacheEntry entry = dataCache.get(key);
-
- if (entry == null) { return false; }
-
- // Clean cache if it is expired
- if ((((CacheEntry) entry).isExpired())) {
- log.debug("Found expired object. Deleting...");
- totalCookies--;
- dataCache.remove(key);
- return false;
- }
-
- // OK, we have it
- return true;
- }
-
- public String retrieve(String key) throws CacheException {
-
- CacheEntry entry = dataCache.get(key);
-
- if (entry == null) { return null; }
-
- // Clean cache if it is expired
- if ((((CacheEntry) entry).isExpired())) {
- log.debug("Found expired object. Deleting...");
- totalCookies--;
- dataCache.remove(key);
- return null;
- }
-
- // OK, we have it
- return entry.value;
- }
-
- public void remove(String key) throws CacheException {
-
- dataCache.remove(key);
- totalCookies--;
- }
-
- public void store(String key, String value, long duration) throws CacheException {
-
- dataCache.put(key, new CacheEntry(value, duration));
- totalCookies++;
- }
-
- private void initFromCookies() throws CacheException {
-
- log.debug("Attempting to initialize cache from client-supplied cookies.");
- // Pull data from cookies
- List<Cookie> relevantCookies = new ArrayList<Cookie>();
- for (Cookie cookie : myCurrentCookies) {
- if (cookie.getName().startsWith(NAME_PREFIX + getName())) {
- relevantCookies.add(cookie);
- }
- }
- if (relevantCookies.isEmpty()) {
- log.debug("No applicable cookies found. Cache is empty.");
- return;
- }
-
- // Sort
- String[] sortedCookieValues = new String[relevantCookies.size()];
- for (Cookie cookie : relevantCookies) {
- String[] tokenizedName = cookie.getName().split(":");
- sortedCookieValues[Integer.parseInt(tokenizedName[tokenizedName.length - 1]) - 1] = cookie.getValue();
- }
- // Concatenate
- StringBuffer concat = new StringBuffer();
- for (String cookieValue : sortedCookieValues) {
- concat.append(cookieValue);
- }
- log.debug("Dumping Encrypted/Encoded Input Cache: " + concat);
-
- try {
- // Decode Base32
- byte[] in = Base32.decode(concat.toString());
-
- // Decrypt
- Cipher cipher = Cipher.getInstance(cipherAlgorithm);
- int ivSize = cipher.getBlockSize();
- byte[] iv = new byte[ivSize];
- Mac mac = Mac.getInstance(macAlgorithm);
- mac.init(secret);
- int macSize = mac.getMacLength();
- if (in.length < ivSize) {
- log.error("Cache is malformed (not enough bytes).");
- throw new CacheException("Cache is malformed (not enough bytes).");
- }
-
- // extract the IV, setup the cipher and extract the encrypted data
- System.arraycopy(in, 0, iv, 0, ivSize);
- IvParameterSpec ivSpec = new IvParameterSpec(iv);
- cipher.init(Cipher.DECRYPT_MODE, secret, ivSpec);
- byte[] encryptedData = new byte[in.length - iv.length];
- System.arraycopy(in, ivSize, encryptedData, 0, in.length - iv.length);
-
- // decrypt the rest of the data andsetup the streams
- byte[] decryptedBytes = cipher.doFinal(encryptedData);
- ByteArrayInputStream byteStream = new ByteArrayInputStream(decryptedBytes);
- GZIPInputStream compressedData = new GZIPInputStream(byteStream);
- ObjectInputStream dataStream = new ObjectInputStream(compressedData);
-
- // extract the components
- byte[] decodedMac = new byte[macSize];
-
- int bytesRead = dataStream.read(decodedMac);
- if (bytesRead != macSize) {
- log.error("Error parsing cache: Unable to extract HMAC.");
- throw new CacheException("Error parsing cache: Unable to extract HMAC.");
- }
-
- String decodedData = (String) dataStream.readObject();
- log.debug("Dumping Raw Input Cache: " + decodedData);
-
- // Verify HMAC
- byte[] generatedMac = mac.doFinal(decodedData.getBytes());
- if (!Arrays.equals(decodedMac, generatedMac)) {
- log.error("Cookie cache data failed integrity check.");
- throw new GeneralSecurityException("Cookie cache data failed integrity check.");
- }
-
- // Parse XML
- DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
- factory.setValidating(false);
- factory.setNamespaceAware(false);
- Element cacheElement = factory.newDocumentBuilder().parse(new InputSource(new StringReader(decodedData)))
- .getDocumentElement();
- NodeList items = cacheElement.getElementsByTagName("Item");
- for (int i = 0; i < items.getLength(); i++) {
- Element item = (Element) items.item(i);
- totalCookies++;
- dataCache.put(item.getAttribute("key"), new CacheEntry(item.getAttribute("value"), new Date(new Long(
- item.getAttribute("expire")))));
- }
-
- } catch (Exception e) {
- log.error("Error decrypting cache data: " + e);
- throw new CacheException("Unable to read cached data.");
- }
- }
-
- private boolean usingDefaultSecret() {
-
- byte[] defaultKey = new byte[]{(byte) 0xC7, (byte) 0x49, (byte) 0x80, (byte) 0xD3, (byte) 0x02, (byte) 0x4A,
- (byte) 0x61, (byte) 0xEF, (byte) 0x25, (byte) 0x5D, (byte) 0xE3, (byte) 0x2F, (byte) 0x57, (byte) 0x51,
- (byte) 0x20, (byte) 0x15, (byte) 0xC7, (byte) 0x49, (byte) 0x80, (byte) 0xD3, (byte) 0x02, (byte) 0x4A,
- (byte) 0x61, (byte) 0xEF};
- byte[] encodedKey = secret.getEncoded();
- return Arrays.equals(defaultKey, encodedKey);
- }
-
- /**
- * Secures, encodes, and writes out (to cookies) cached data.
- */
- private void flushCache() throws CacheException {
-
- log.debug("Flushing cache.");
- log.debug("Encrypting cache data.");
-
- // Create XML/String representation of all cache data
- String stringData = null;
-
- try {
-
- DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
- docFactory.setNamespaceAware(false);
- Document placeHolder = docFactory.newDocumentBuilder().newDocument();
-
- Element cacheNode = placeHolder.createElement("Cache");
- for (Entry<String, CacheEntry> entry : dataCache.entrySet()) {
- Element itemNode = placeHolder.createElement("Item");
- itemNode.setAttribute("key", entry.getKey());
- itemNode.setAttribute("value", entry.getValue().value);
- itemNode.setAttribute("expire", new Long(entry.getValue().expiration.getTime()).toString());
- cacheNode.appendChild(itemNode);
- }
-
- TransformerFactory factory = TransformerFactory.newInstance();
- DOMSource source = new DOMSource(cacheNode);
- Transformer transformer = factory.newTransformer();
- transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
- StringWriter stringWriter = new StringWriter();
- StreamResult result = new StreamResult(stringWriter);
- transformer.transform(source, result);
- stringData = stringWriter.toString().replaceAll(">\\s<", "><");
- log.debug("Dumping Raw Cache: " + stringData);
-
- } catch (Exception e) {
- log.error("Error encoding cache data: " + e);
- throw new CacheException("Unable to cache data.");
- }
-
- try {
-
- // Setup a gzipped data stream
- ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
- GZIPOutputStream compressedStream = new GZIPOutputStream(byteStream);
- ObjectOutputStream dataStream = new ObjectOutputStream(compressedStream);
-
- // Write data and HMAC to stream
- Mac mac = Mac.getInstance(macAlgorithm);
- mac.init(secret);
- dataStream.write(mac.doFinal(stringData.getBytes()));
- dataStream.writeObject(stringData);
-
- // Flush
- // dataStream.flush();
- compressedStream.flush();
- compressedStream.finish();
- byteStream.flush();
-
- // Setup encryption lib
- Cipher cipher = Cipher.getInstance(cipherAlgorithm);
- byte[] iv = new byte[cipher.getBlockSize()];
- random.nextBytes(iv);
- IvParameterSpec ivSpec = new IvParameterSpec(iv);
- cipher.init(Cipher.ENCRYPT_MODE, secret, ivSpec);
-
- // Creat byte array of IV and encrypted cache
- byte[] encryptedData = cipher.doFinal(byteStream.toByteArray());
- byte[] cacheBytes = new byte[iv.length + encryptedData.length];
- // Write IV
- System.arraycopy(iv, 0, cacheBytes, 0, iv.length);
- // Write encrypted cache
- System.arraycopy(encryptedData, 0, cacheBytes, iv.length, encryptedData.length);
-
- // Base32 encode
- String encodedData = Base32.encode(cacheBytes);
- log.debug("Dumping Encrypted/Encoded Cache: " + encodedData);
-
- // Put into cookies
- interleaveInCookies(encodedData);
-
- } catch (Exception e) {
- log.error("Error encrypting cache data: " + e);
- throw new CacheException("Unable to cache data.");
- }
- }
-
- /**
- * Writes encoded data across multiple cookies
- */
- private void interleaveInCookies(String data) {
-
- log.debug("Writing cache to cookies.");
-
- // Convert the String data to a list of cookies
- Map<String, Cookie> cookiesToResponse = new HashMap<String, Cookie>();
- StringBuffer bufferredData = new StringBuffer(data);
- int i = 1;
- while (bufferredData != null && bufferredData.length() > 0) {
- Cookie cookie = null;
- String name = NAME_PREFIX + getName() + ":" + i++;
- if (bufferredData.length() <= getCookieSpace(name)) {
- cookie = new Cookie(name, bufferredData.toString());
- bufferredData = null;
- } else {
- cookie = new Cookie(name, bufferredData.substring(0, getCookieSpace(name) - 1));
- bufferredData.delete(0, getCookieSpace(name) - 1);
- }
- cookiesToResponse.put(cookie.getName(), cookie);
- }
-
- // Expire cookies that we used previously but no longer need
- for (Cookie currCookie : myCurrentCookies) {
- if (!cookiesToResponse.containsKey(currCookie.getName())) {
- currCookie.setMaxAge(0);
- currCookie.setValue(null);
- cookiesToResponse.put(currCookie.getName(), currCookie);
- }
- }
-
- // Write our cookies to the response object
- for (Cookie cookie : cookiesToResponse.values()) {
- response.addCookie(cookie);
- }
-
- // Update our cached copy of the cookies
- myCurrentCookies = cookiesToResponse.values();
- }
-
- /**
- * Returns the amount of value space available in cookies we create
- */
- private int getCookieSpace(String cookieName) {
-
- // If we add other cookie variables, we would need to adjust this algorithm appropriately
- StringBuffer used = new StringBuffer();
- used.append("Set-Cookie: ");
- used.append(cookieName + "=" + " ");
- return CHUNK_SIZE - used.length() - 2;
- }
-
-}
+++ /dev/null
-/*
- * Copyright [2005] [University Corporation for Advanced Internet Development, Inc.]
- *
- * Licensed 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 edu.internet2.middleware.shibboleth.common.provider;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
-import java.io.IOException;
-import java.io.StreamCorruptedException;
-import java.security.GeneralSecurityException;
-import java.security.InvalidKeyException;
-import java.security.KeyException;
-import java.security.KeyStore;
-import java.security.KeyStoreException;
-import java.security.NoSuchAlgorithmException;
-import java.security.Principal;
-import java.security.SecureRandom;
-import java.security.UnrecoverableKeyException;
-import java.security.cert.CertificateException;
-import java.util.Arrays;
-import java.util.zip.GZIPInputStream;
-import java.util.zip.GZIPOutputStream;
-
-import javax.crypto.Cipher;
-import javax.crypto.Mac;
-import javax.crypto.NoSuchPaddingException;
-import javax.crypto.SecretKey;
-import javax.crypto.spec.IvParameterSpec;
-
-import org.apache.log4j.Logger;
-import org.opensaml.SAMLException;
-import org.opensaml.SAMLNameIdentifier;
-import org.w3c.dom.Element;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-
-import edu.internet2.middleware.shibboleth.common.IdentityProvider;
-import edu.internet2.middleware.shibboleth.common.InvalidNameIdentifierException;
-import edu.internet2.middleware.shibboleth.common.LocalPrincipal;
-import edu.internet2.middleware.shibboleth.common.NameIdentifierMapping;
-import edu.internet2.middleware.shibboleth.common.NameIdentifierMappingException;
-import edu.internet2.middleware.shibboleth.common.ServiceProvider;
-import edu.internet2.middleware.shibboleth.common.ShibResource;
-import edu.internet2.middleware.shibboleth.utils.Base32;
-
-/**
- * {@link NameIdentifierMapping}implementation that uses symmetric encryption to store principal data inside Shibboleth
- * Attribute Query Handles.
- *
- * @author Walter Hoehn
- * @author Derek Morr
- */
-public class CryptoShibHandle extends AQHNameIdentifierMapping implements NameIdentifierMapping {
-
- private static Logger log = Logger.getLogger(CryptoShibHandle.class.getName());
- protected SecretKey secret;
- private SecureRandom random = new SecureRandom();
- private String cipherAlgorithm = "DESede/CBC/PKCS5Padding";
- private String macAlgorithm = "HmacSHA1";
- private String storeType = "JCEKS";
-
- public CryptoShibHandle(Element config) throws NameIdentifierMappingException {
-
- super(config);
- try {
-
- String keyStorePath = getElementConfigData(config, "KeyStorePath", true);
- String keyStorePassword = getElementConfigData(config, "KeyStorePassword", true);
- String keyStoreKeyAlias = getElementConfigData(config, "KeyStoreKeyAlias", true);
- String keyStoreKeyPassword = getElementConfigData(config, "KeyStoreKeyPassword", true);
-
- String rawStoreType = getElementConfigData(config, "KeyStoreType", false);
- if (rawStoreType != null && !rawStoreType.equals("")) {
- storeType = rawStoreType;
- }
- String rawCipherAlgorithm = getElementConfigData(config, "Cipher", false);
- if (rawCipherAlgorithm != null && !rawCipherAlgorithm.equals("")) {
- cipherAlgorithm = rawCipherAlgorithm;
- }
- String rawMacAlgorithm = getElementConfigData(config, "MAC", false);
- if (rawMacAlgorithm != null && !rawMacAlgorithm.equals("")) {
- macAlgorithm = rawMacAlgorithm;
- }
-
- KeyStore keyStore = KeyStore.getInstance(storeType);
- keyStore.load(new ShibResource(keyStorePath, this.getClass()).getInputStream(), keyStorePassword
- .toCharArray());
- secret = (SecretKey) keyStore.getKey(keyStoreKeyAlias, keyStoreKeyPassword.toCharArray());
-
- // Before we finish initilization, make sure that things are working
- testEncryption();
-
- if (usingDefaultSecret()) {
- log.warn("You are running Crypto AQH Name Mapping with the "
- + "default secret key. This is UNSAFE! Please change "
- + "this configuration and restart the IdP.");
- }
- } catch (StreamCorruptedException e) {
- if (System.getProperty("java.version").startsWith("1.4.2")) {
- log.error("There is a bug in some versions of Java 1.4.2.x that "
- + "prevent JCEKS keystores from being loaded properly. "
- + "You probably need to upgrade or downgrade your JVM in order to make this work.");
- }
- log.error("An error occurred while loading the java keystore. Unable to initialize "
- + "Crypto Name Mapping: " + e);
- throw new NameIdentifierMappingException(
- "An error occurred while loading the java keystore. Unable to initialize Crypto "
- + "Name Mapping.");
- } catch (KeyStoreException e) {
- log.error("An error occurred while loading the java keystore. Unable to initialize Crypto "
- + "Name Mapping: " + e);
- throw new NameIdentifierMappingException(
- "An error occurred while loading the java keystore. Unable to initialize Crypto Name Mapping.");
- } catch (CertificateException e) {
- log.error("The java keystore contained corrupted data. Unable to initialize Crypto Name Mapping: " + e);
- throw new NameIdentifierMappingException(
- "The java keystore contained corrupted data. Unable to initialize Crypto Name Mapping.");
- } catch (NoSuchAlgorithmException e) {
- log.error("Appropriate JCE provider not found in the java environment. Unable "
- + "to initialize Crypto Name Mapping: " + e);
- throw new NameIdentifierMappingException(
- "Appropriate JCE provider not found in the java environment. Unable to initialize Crypto Name Mapping.");
- } catch (IOException e) {
- log.error("An error accessing while loading the java keystore. Unable to initialize Crypto Name "
- + "Mapping: " + e);
- throw new NameIdentifierMappingException(
- "An error occurred while accessing the java keystore. Unable to initialize Crypto Name Mapping.");
- } catch (UnrecoverableKeyException e) {
- log.error("Secret could not be loaded from the java keystore. Verify that the alias and "
- + "password are correct: " + e);
- throw new NameIdentifierMappingException(
- "Secret could not be loaded from the java keystore. Verify that the alias and password are correct. ");
- }
- }
-
- /**
- * Decode an encrypted handle inside a SAMLNameIdentifier back into a principal
- */
- public Principal getPrincipal(SAMLNameIdentifier nameId, ServiceProvider sProv, IdentityProvider idProv)
- throws NameIdentifierMappingException, InvalidNameIdentifierException {
- verifyQualifier(nameId, idProv);
- return getPrincipal(nameId.getName());
- }
-
- /**
- * Decode an encrypted handle string back into a principal
- */
- public Principal getPrincipal(String name)
- throws NameIdentifierMappingException, InvalidNameIdentifierException {
-
- try {
- byte[] in = Base32.decode(name);
-
- Cipher cipher = Cipher.getInstance(cipherAlgorithm);
- int ivSize = cipher.getBlockSize();
- byte[] iv = new byte[ivSize];
-
- Mac mac = Mac.getInstance(macAlgorithm);
- mac.init(secret);
- int macSize = mac.getMacLength();
-
- if (in.length < ivSize) {
- log.error("Attribute Query Handle is malformed (not enough bytes).");
- throw new NameIdentifierMappingException("Attribute Query Handle is malformed (not enough bytes).");
- }
-
- // extract the IV, setup the cipher and extract the encrypted handle
- System.arraycopy(in, 0, iv, 0, ivSize);
- IvParameterSpec ivSpec = new IvParameterSpec(iv);
- cipher.init(Cipher.DECRYPT_MODE, secret, ivSpec);
-
- byte[] encryptedHandle = new byte[in.length - iv.length];
- System.arraycopy(in, ivSize, encryptedHandle, 0, in.length - iv.length);
-
- // decrypt the rest of the data and setup the streams
- byte[] decryptedBytes = cipher.doFinal(encryptedHandle);
- ByteArrayInputStream byteStream = new ByteArrayInputStream(decryptedBytes);
- GZIPInputStream compressedData = new GZIPInputStream(byteStream);
- DataInputStream dataStream = new DataInputStream(compressedData);
-
- // extract the components
- byte[] decodedMac = new byte[macSize];
- int bytesRead = dataStream.read(decodedMac);
- if (bytesRead != macSize) {
- log.error("Error parsing handle: Unable to extract HMAC.");
- throw new NameIdentifierMappingException("Error parsing handle: Unable to extract HMAC.");
- }
- long decodedExpirationTime = dataStream.readLong();
- String decodedPrincipal = dataStream.readUTF();
-
- HMACHandleEntry macHandleEntry = createHMACHandleEntry(new LocalPrincipal(decodedPrincipal));
- macHandleEntry.setExpirationTime(decodedExpirationTime);
- byte[] generatedMac = macHandleEntry.getMAC(mac);
-
- if (macHandleEntry.isExpired()) {
- log.debug("Attribute Query Handle is expired.");
- throw new InvalidNameIdentifierException("Attribute Query Handle is expired.", errorCodes);
- }
-
- if (!Arrays.equals(decodedMac, generatedMac)) {
- log.warn("Attribute Query Handle failed integrity check.");
- throw new NameIdentifierMappingException("Attribute Query Handle failed integrity check.");
- }
-
- log.debug("Attribute Query Handle recognized.");
- return macHandleEntry.principal;
-
- } catch (NoSuchAlgorithmException e) {
- log.error("Appropriate JCE provider not found in the java environment. Could not load Algorithm: " + e);
- throw new NameIdentifierMappingException(
- "Appropriate JCE provider not found in the java environment. Could not load Algorithm.");
- } catch (NoSuchPaddingException e) {
- log.error("Appropriate JCE provider not found in the java environment. Could not load Padding "
- + "method: " + e);
- throw new NameIdentifierMappingException(
- "Appropriate JCE provider not found in the java environment. Could not load Padding method.");
- } catch (InvalidKeyException e) {
- log.error("Could not use the supplied secret key: " + e);
- throw new NameIdentifierMappingException("Could not use the supplied secret key.");
- } catch (GeneralSecurityException e) {
- log.warn("Unable to decrypt the supplied Attribute Query Handle: " + e);
- throw new NameIdentifierMappingException("Unable to decrypt the supplied Attribute Query Handle.");
- } catch (IOException e) {
- log.warn("IO error while decoding handle.");
- throw new NameIdentifierMappingException("IO error while decoding handle.");
- }
- }
-
- /**
- * Encodes a principal into a cryptographic handle per the following method below, and then constructs
- * a SAMLNameIdentifier out of it.
- */
- public SAMLNameIdentifier getNameIdentifier(LocalPrincipal principal, ServiceProvider sProv,
- IdentityProvider idProv) throws NameIdentifierMappingException {
- try {
- SAMLNameIdentifier nameid = SAMLNameIdentifier.getInstance(getNameIdentifierFormat().toString());
- nameid.setName(getName(principal).replaceAll(System.getProperty("line.separator"), ""));
- nameid.setNameQualifier(idProv.getProviderId());
- return nameid;
- } catch (SAMLException e) {
- throw new NameIdentifierMappingException("Unable to generate Attribute Query Handle: " + e);
- }
- }
-
- /**
- * Encodes a principal into a cryptographic handle Format of encoded handle: [IV][HMAC][TTL][principal] where: [IV] =
- * the Initialization Vector; byte-array [HMAC] = the HMAC; byte array [exprTime] = expiration time of the handle; 8
- * bytes; Big-endian [principal] = the principal; a UTF-8-encoded string The [HMAC][exprTime][princLen][principal]
- * byte stream is GZIPped. The IV is pre-pended to this byte stream, and the result is Base32-encoded. We don't need
- * to encode the IV or MAC's lengths. They can be obtained from Cipher.getBlockSize() and Mac.getMacLength(),
- * respectively.
- */
- public String getName(LocalPrincipal principal)
- throws NameIdentifierMappingException {
-
- if (principal == null) {
- log.error("A principal must be supplied for Attribute Query Handle creation.");
- throw new IllegalArgumentException("A principal must be supplied for Attribute Query Handle creation.");
- }
-
- try {
-
- Mac mac = Mac.getInstance(macAlgorithm);
- mac.init(secret);
- HMACHandleEntry macHandleEntry = createHMACHandleEntry(principal);
-
- Cipher cipher = Cipher.getInstance(cipherAlgorithm);
- byte[] iv = new byte[cipher.getBlockSize()];
- random.nextBytes(iv);
- IvParameterSpec ivSpec = new IvParameterSpec(iv);
- cipher.init(Cipher.ENCRYPT_MODE, secret, ivSpec);
-
- ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
- GZIPOutputStream compressedStream = new GZIPOutputStream(byteStream);
- DataOutputStream dataStream = new DataOutputStream(compressedStream);
-
- dataStream.write(macHandleEntry.getMAC(mac));
- dataStream.writeLong(macHandleEntry.getExpirationTime());
- dataStream.writeUTF(principal.getName());
-
- dataStream.flush();
- compressedStream.flush();
- compressedStream.finish();
- byteStream.flush();
-
- byte[] encryptedData = cipher.doFinal(byteStream.toByteArray());
-
- byte[] handleBytes = new byte[iv.length + encryptedData.length];
- System.arraycopy(iv, 0, handleBytes, 0, iv.length);
- System.arraycopy(encryptedData, 0, handleBytes, iv.length, encryptedData.length);
-
- return Base32.encode(handleBytes);
-
- } catch (KeyException e) {
- log.error("Could not use the supplied secret key: " + e);
- throw new NameIdentifierMappingException("Could not use the supplied secret key.");
- } catch (GeneralSecurityException e) {
- log.error("Appropriate JCE provider not found in the java environment. Could not load Cipher: " + e);
- throw new NameIdentifierMappingException(
- "Appropriate JCE provider not found in the java environment. Could not load Cipher.");
- } catch (IOException e) {
- log.error("IO error while decoding handle.");
- throw new NameIdentifierMappingException("IO error while decoding handle.");
- }
-
- }
-
- private String getElementConfigData(Element e, String itemName, boolean required)
- throws NameIdentifierMappingException {
-
- NodeList itemElements = e.getElementsByTagNameNS(NameIdentifierMapping.mappingNamespace, itemName);
-
- if (itemElements.getLength() < 1) {
- if (required) {
- log.error(itemName + " not specified.");
- throw new NameIdentifierMappingException("Crypto Name Mapping requires a <" + itemName
- + "> specification.");
- } else {
- return null;
- }
- }
-
- if (itemElements.getLength() > 1) {
- log.error("Multiple " + itemName + " specifications, using first.");
- }
-
- Node tnode = itemElements.item(0).getFirstChild();
- String item = null;
- if (tnode != null && tnode.getNodeType() == Node.TEXT_NODE) {
- item = tnode.getNodeValue();
- }
- if (item == null || item.equals("")) {
- log.error(itemName + " not specified.");
- throw new NameIdentifierMappingException("Crypto Name Mapping requires a valid <" + itemName
- + "> specification.");
- }
- return item;
- }
-
- private void testEncryption() throws NameIdentifierMappingException {
-
- String decrypted;
- try {
- Cipher cipher = Cipher.getInstance(cipherAlgorithm);
- byte[] iv = new byte[cipher.getBlockSize()];
- random.nextBytes(iv);
- IvParameterSpec ivSpec = new IvParameterSpec(iv);
- cipher.init(Cipher.ENCRYPT_MODE, secret, ivSpec);
- byte[] cipherText = cipher.doFinal("test".getBytes());
- cipher = Cipher.getInstance(cipherAlgorithm);
- cipher.init(Cipher.DECRYPT_MODE, secret, ivSpec);
- decrypted = new String(cipher.doFinal(cipherText));
- } catch (Exception e) {
- log.error("Round trip encryption/decryption test unsuccessful: " + e);
- throw new NameIdentifierMappingException("Round trip encryption/decryption test unsuccessful.");
- }
-
- if (decrypted == null || !decrypted.equals("test")) {
- log.error("Round trip encryption/decryption test unsuccessful. Decrypted text did not match.");
- throw new NameIdentifierMappingException("Round trip encryption/decryption test unsuccessful.");
- }
-
- byte[] code;
- try {
- Mac mac = Mac.getInstance(macAlgorithm);
- mac.init(secret);
- mac.update("foo".getBytes());
- code = mac.doFinal();
-
- } catch (Exception e) {
- log.error("Message Authentication test unsuccessful: " + e);
- throw new NameIdentifierMappingException("Message Authentication test unsuccessful.");
- }
-
- if (code == null) {
- log.error("Message Authentication test unsuccessful.");
- throw new NameIdentifierMappingException("Message Authentication test unsuccessful.");
- }
- }
-
- private boolean usingDefaultSecret() {
-
- byte[] defaultKey = new byte[]{(byte) 0xC7, (byte) 0x49, (byte) 0x80, (byte) 0xD3, (byte) 0x02, (byte) 0x4A,
- (byte) 0x61, (byte) 0xEF, (byte) 0x25, (byte) 0x5D, (byte) 0xE3, (byte) 0x2F, (byte) 0x57, (byte) 0x51,
- (byte) 0x20, (byte) 0x15, (byte) 0xC7, (byte) 0x49, (byte) 0x80, (byte) 0xD3, (byte) 0x02, (byte) 0x4A,
- (byte) 0x61, (byte) 0xEF};
- byte[] encodedKey = secret.getEncoded();
- return Arrays.equals(defaultKey, encodedKey);
- }
-
- protected HMACHandleEntry createHMACHandleEntry(LocalPrincipal principal) {
-
- return new HMACHandleEntry(principal, handleTTL);
- }
-
-}
-
-/**
- * <code>HandleEntry</code> extension class that performs message authentication.
- */
-
-class HMACHandleEntry extends HandleEntry {
-
- protected HMACHandleEntry(LocalPrincipal principal, long TTL) {
-
- super(principal, TTL);
- }
-
- private static byte[] getLongBytes(long longValue) {
-
- try {
- ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
- DataOutputStream dataStream = new DataOutputStream(byteStream);
-
- dataStream.writeLong(longValue);
- dataStream.flush();
- byteStream.flush();
-
- return byteStream.toByteArray();
- } catch (IOException ex) {
- return null;
- }
- }
-
- public byte[] getMAC(Mac mac) {
-
- mac.update(getLongBytes(expirationTime));
- mac.update(principal.getName().getBytes());
-
- return mac.doFinal();
- }
-}
+++ /dev/null
-/*
- * Copyright [2005] [University Corporation for Advanced Internet Development, Inc.]
- *
- * Licensed 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 edu.internet2.middleware.shibboleth.common.provider;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Set;
-import java.util.Map.Entry;
-
-import org.apache.log4j.Logger;
-
-import edu.internet2.middleware.shibboleth.common.Cache;
-import edu.internet2.middleware.shibboleth.common.CacheException;
-
-/**
- * <code>Cache</code> implementation that uses java objects to cache data. This implementation will reap expired
- * entries.
- *
- * @author Walter Hoehn
- */
-
-public class MemoryCache extends BaseCache implements Cache {
-
- private MemoryCacheCleaner cleaner = new MemoryCacheCleaner();
- private static Logger log = Logger.getLogger(MemoryCache.class.getName());
- private Map<String, CacheEntry> entries = Collections.synchronizedMap(new HashMap<String, CacheEntry>());
-
- public MemoryCache(String name) {
-
- super(name, Cache.CacheType.SERVER_SIDE);
- }
-
- public boolean contains(String key) throws CacheException {
-
- CacheEntry entry = entries.get(key);
- if (entry == null) { return false; }
-
- // Clean cache if it is expired
- if (entry.isExpired()) {
- log.debug("Found expired object. Deleting...");
- entries.remove(key);
- return false;
- }
-
- // OK, we have it
- return true;
- }
-
- public void remove(String key) throws CacheException {
-
- entries.remove(key);
- }
-
- public String retrieve(String key) throws CacheException {
-
- CacheEntry entry = entries.get(key);
- if (entry == null) { return null; }
-
- // Clean cache if it is expired
- if (entry.isExpired()) {
- log.debug("Found expired object. Deleting...");
- entries.remove(key);
- return null;
- }
-
- return entry.value;
- }
-
- public void store(String key, String value, long duration) throws CacheException {
-
- entries.put(key, new CacheEntry(value, duration));
- }
-
- protected void destroy() {
-
- synchronized (cleaner) {
- if (cleaner != null) {
- cleaner.shutdown = true;
- cleaner.interrupt();
- }
- }
- }
-
- protected void finalize() throws Throwable {
-
- super.finalize();
- destroy();
- }
-
- private class MemoryCacheCleaner extends Thread {
-
- private boolean shutdown = false;
- private Thread master;
-
- private MemoryCacheCleaner() {
-
- super("edu.internet2.middleware.shibboleth.idp.common.provider.MemoryCache.MemoryCacheCleaner");
- this.master = Thread.currentThread();
- setDaemon(true);
- if (getPriority() > Thread.MIN_PRIORITY) {
- setPriority(getPriority() - 1);
- }
- log.debug("Starting memory-based cache cleanup thread (" + getName() + ").");
- start();
- }
-
- public void run() {
-
- try {
- sleep(60 * 1000); // one minute
- } catch (InterruptedException e) {
- log.debug("Memory-based cache cleanup interrupted (" + getName() + ").");
- }
- while (true) {
- try {
- if (!master.isAlive()) {
- shutdown = true;
- log.debug("Memory-based cache cleaner is orphaned (" + getName() + ").");
- }
- if (shutdown) {
- log.debug("Stopping Memory-based cache cleanup thread (" + getName() + ").");
- return;
- }
- log.debug("Memory-based cache cleanup thread searching for stale entries (" + getName() + ").");
- Set<String> needsDeleting = new HashSet<String>();
- synchronized (entries) {
- Iterator<Entry<String, CacheEntry>> iterator = entries.entrySet().iterator();
- while (iterator.hasNext()) {
- Entry<String, CacheEntry> entry = iterator.next();
- CacheEntry cacheEntry = entry.getValue();
- if (cacheEntry.isExpired()) {
- needsDeleting.add(entry.getKey());
- }
- }
-
- }
- // release the lock to be friendly
- Iterator deleteIterator = needsDeleting.iterator();
- while (deleteIterator.hasNext()) {
- synchronized (entries) {
- log.debug("Expiring an entry from the memory cache (" + getName() + ").");
- entries.remove(deleteIterator.next());
- }
- }
- sleep(60 * 1000); // one minute
- } catch (InterruptedException e) {
- log.debug("Memory-based cache cleanup interrupted (" + getName() + ").");
- }
- }
- }
- }
-}
+++ /dev/null
-/*
- * Copyright [2005] [University Corporation for Advanced Internet Development, Inc.]
- *
- * Licensed 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 edu.internet2.middleware.shibboleth.common.provider;
-
-import java.security.Principal;
-
-import org.apache.log4j.Logger;
-import org.opensaml.SAMLException;
-import org.opensaml.SAMLNameIdentifier;
-import org.w3c.dom.Element;
-
-import edu.internet2.middleware.shibboleth.common.IdentityProvider;
-import edu.internet2.middleware.shibboleth.common.InvalidNameIdentifierException;
-import edu.internet2.middleware.shibboleth.common.LocalPrincipal;
-import edu.internet2.middleware.shibboleth.common.NameIdentifierMapping;
-import edu.internet2.middleware.shibboleth.common.NameIdentifierMappingException;
-import edu.internet2.middleware.shibboleth.common.ServiceProvider;
-
-/**
- * {@link NameIdentifierMapping}implementation to use when the SAML name identifier format matches the Shibboleth
- * internal representation of the principal.
- *
- * @author Walter Hoehn
- */
-public class PrincipalNameIdentifier extends BaseNameIdentifierMapping {
-
- private static Logger log = Logger.getLogger(PrincipalNameIdentifier.class.getName());
-
- public PrincipalNameIdentifier(Element config) throws NameIdentifierMappingException {
-
- super(config);
- }
-
- public Principal getPrincipal(SAMLNameIdentifier nameId, ServiceProvider sProv, IdentityProvider idProv)
- throws NameIdentifierMappingException, InvalidNameIdentifierException {
-
- verifyQualifier(nameId, idProv);
- return new LocalPrincipal(nameId.getName());
- }
-
- public SAMLNameIdentifier getNameIdentifier(LocalPrincipal principal, ServiceProvider sProv, IdentityProvider idProv)
- throws NameIdentifierMappingException {
-
- if (principal == null) {
- log.error("A principal must be supplied for Name Identifier creation.");
- throw new IllegalArgumentException("A principal must be supplied for Name Identifier creation.");
- }
-
- try {
- SAMLNameIdentifier nameid = SAMLNameIdentifier.getInstance(getNameIdentifierFormat().toString());
- nameid.setName(principal.getName());
- nameid.setNameQualifier(idProv.getProviderId());
- return nameid;
- } catch (SAMLException e) {
- throw new NameIdentifierMappingException("Unable to generate Name Identifier: " + e);
- }
- }
-}
\ No newline at end of file
+++ /dev/null
-/*
- * Copyright [2005] [University Corporation for Advanced Internet Development, Inc.]
- *
- * Licensed 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 edu.internet2.middleware.shibboleth.common.provider;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpSession;
-
-import org.apache.log4j.Logger;
-
-import edu.internet2.middleware.shibboleth.common.Cache;
-import edu.internet2.middleware.shibboleth.common.CacheException;
-
-/**
- * <code>Cache</code> implementation that uses Servlet API sessions to cache data. This implementation will reap
- * expired entries as they are accessed, but primarily relies on the servlet container and the web browser to handle
- * invalidation of cached values.
- *
- * @author Walter Hoehn
- */
-public class ServletSessionCache extends BaseCache implements Cache {
-
- private static Logger log = Logger.getLogger(ServletSessionCache.class.getName());
- private HttpSession session;
-
- ServletSessionCache(String name, HttpServletRequest request) {
-
- super(name, Cache.CacheType.CLIENT_SERVER_SHARED);
-
- if (request == null) { throw new IllegalArgumentException(
- "Servlet request is required for construction of BaseCache."); }
-
- this.session = request.getSession();
- }
-
- private String getInternalKeyName(String externalKey) {
-
- return this.getClass().getName() + "::" + getName() + "::" + externalKey;
- }
-
- public boolean contains(String key) {
-
- // Lookup object
- Object object = session.getAttribute(getInternalKeyName(key));
- if (object == null || !(object instanceof CacheEntry)) { return false; }
-
- // Clean cache if it is expired
- if (((CacheEntry) object).isExpired()) {
- log.debug("Found expired object. Deleting...");
- session.removeAttribute(getInternalKeyName(key));
- return false;
- }
-
- // OK, we have it
- return true;
- }
-
- public String retrieve(String key) {
-
- // Lookup object
- Object object = session.getAttribute(getInternalKeyName(key));
- if (object == null || !(object instanceof CacheEntry)) { return null; }
-
- // Clean cache if it is expired
- if (((CacheEntry) object).isExpired()) {
- log.debug("Found expired object. Deleting...");
- session.removeAttribute(getInternalKeyName(key));
- return null;
- }
-
- // OK, we have it
- return ((CacheEntry) object).value;
- }
-
- public void store(String key, String value, long duration) {
-
- session.setAttribute(getInternalKeyName(key), new CacheEntry(value, duration));
- }
-
- public void remove(String key) throws CacheException {
-
- session.removeAttribute(getInternalKeyName(key));
- }
-
-}
+++ /dev/null
-/*
- * Copyright [2005] [University Corporation for Advanced Internet Development, Inc.]
- *
- * Licensed 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 edu.internet2.middleware.shibboleth.common.provider;
-
-import java.security.Principal;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Set;
-import java.util.Map.Entry;
-
-import org.apache.log4j.Logger;
-import org.opensaml.SAMLConfig;
-import org.opensaml.SAMLException;
-import org.opensaml.SAMLNameIdentifier;
-import org.w3c.dom.Element;
-
-import edu.internet2.middleware.shibboleth.common.IdentityProvider;
-import edu.internet2.middleware.shibboleth.common.InvalidNameIdentifierException;
-import edu.internet2.middleware.shibboleth.common.LocalPrincipal;
-import edu.internet2.middleware.shibboleth.common.NameIdentifierMapping;
-import edu.internet2.middleware.shibboleth.common.NameIdentifierMappingException;
-import edu.internet2.middleware.shibboleth.common.ServiceProvider;
-
-/**
- * {@link NameIdentifierMapping}implementation that uses an in-memory cache to store mappings between principal names
- * and Shibboleth Attribute Query Handles.
- *
- * @author Walter Hoehn
- */
-public class SharedMemoryShibHandle extends AQHNameIdentifierMapping implements NameIdentifierMapping {
-
- protected HandleCache cache = HandleCache.instance();
- private static Logger log = Logger.getLogger(SharedMemoryShibHandle.class.getName());
- private static SAMLConfig config = SAMLConfig.instance();
-
- public SharedMemoryShibHandle(Element config) throws NameIdentifierMappingException {
-
- super(config);
- }
-
- /*
- * (non-Javadoc)
- *
- * @see edu.internet2.middleware.shibboleth.common.NameIdentifierMapping#getNameIdentifier(edu.internet2.middleware.shibboleth.common.LocalPrincipal,
- * edu.internet2.middleware.shibboleth.common.ServiceProvider,
- * edu.internet2.middleware.shibboleth.common.IdentityProvider)
- */
- public SAMLNameIdentifier getNameIdentifier(LocalPrincipal principal, ServiceProvider sProv, IdentityProvider idProv)
- throws NameIdentifierMappingException {
-
- if (principal == null) {
- log.error("A principal must be supplied for Attribute Query Handle creation.");
- throw new IllegalArgumentException("A principal must be supplied for Attribute Query Handle creation.");
- }
- try {
- String handle = new String(config.getDefaultIDProvider().getIdentifier());
- log.debug("Assigning handle (" + handle + ") to principal (" + principal.getName() + ").");
- synchronized (cache.handleEntries) {
- cache.handleEntries.put(handle, createHandleEntry(principal));
- }
-
- SAMLNameIdentifier nameid = SAMLNameIdentifier.getInstance(getNameIdentifierFormat().toString());
- nameid.setName(handle);
- nameid.setNameQualifier(idProv.getProviderId());
- return nameid;
-
- } catch (SAMLException e) {
- throw new NameIdentifierMappingException("Unable to generate Attribute Query Handle: " + e);
- }
-
- }
-
- /*
- * (non-Javadoc)
- *
- * @see edu.internet2.middleware.shibboleth.common.NameIdentifierMapping#getPrincipal(org.opensaml.SAMLNameIdentifier,
- * edu.internet2.middleware.shibboleth.common.ServiceProvider,
- * edu.internet2.middleware.shibboleth.common.IdentityProvider)
- */
- public Principal getPrincipal(SAMLNameIdentifier nameId, ServiceProvider sProv, IdentityProvider idProv)
- throws NameIdentifierMappingException, InvalidNameIdentifierException {
-
- verifyQualifier(nameId, idProv);
-
- synchronized (cache.handleEntries) {
- if (!cache.handleEntries.containsKey(nameId.getName())) {
- log.debug("The Name Mapping Cache does not contain an entry for this Attribute Query Handle.");
- throw new InvalidNameIdentifierException(
- "The Name Mapping Cache does not contain an entry for this Attribute Query Handle.", errorCodes);
- }
- }
-
- HandleEntry handleEntry;
- synchronized (cache.handleEntries) {
- handleEntry = (HandleEntry) cache.handleEntries.get(nameId.getName());
- }
-
- if (handleEntry.isExpired()) {
- log.debug("Attribute Query Handle is expired.");
- synchronized (cache.handleEntries) {
- cache.handleEntries.remove(nameId.getName());
- }
- throw new InvalidNameIdentifierException("Attribute Query Handle is expired.", errorCodes);
- } else {
- log.debug("Attribute Query Handle recognized.");
- return handleEntry.principal;
- }
- }
-
- public void destroy() {
-
- cache.destroy();
- }
-
-}
-
-class HandleCache {
-
- protected Map handleEntries = new HashMap();
- private static HandleCache instance;
- protected MemoryRepositoryCleaner cleaner = new MemoryRepositoryCleaner();
- private static Logger log = Logger.getLogger(HandleCache.class.getName());
-
- protected HandleCache() {
-
- }
-
- public static synchronized HandleCache instance() {
-
- if (instance == null) {
- instance = new HandleCache();
- return instance;
- }
- return instance;
- }
-
- protected void finalize() throws Throwable {
-
- super.finalize();
- destroy();
- }
-
- protected void destroy() {
-
- synchronized (cleaner) {
- if (cleaner != null) {
- cleaner.shutdown = true;
- cleaner.interrupt();
- }
- }
- }
-
- private class MemoryRepositoryCleaner extends Thread {
-
- private boolean shutdown = false;
- private Thread master;
-
- public MemoryRepositoryCleaner() {
-
- super(
- "edu.internet2.middleware.shibboleth.common.provider.SharedMemoryShibHandle.HandleCache.MemoryRepositoryCleaner");
- this.master = Thread.currentThread();
- setDaemon(true);
- if (getPriority() > Thread.MIN_PRIORITY) {
- setPriority(getPriority() - 1);
- }
- log.debug("Starting memory-based shib handle cache cleanup thread.");
- start();
- }
-
- public void run() {
-
- try {
- sleep(60 * 1000); // one minute
- } catch (InterruptedException e) {
- log.debug("Memory-based shib handle cache cleanup interrupted.");
- }
- while (true) {
- try {
- if (!master.isAlive()) {
- shutdown = true;
- log.debug("Memory-based shib handle cache cleaner is orphaned.");
- }
- if (shutdown) {
- log.debug("Stopping Memory-based shib handle cache cleanup thread.");
- return;
- }
- log.debug("Memory cache handle cache cleanup thread searching for stale entries.");
- Set needsDeleting = new HashSet();
- synchronized (handleEntries) {
- Iterator iterator = handleEntries.entrySet().iterator();
- while (iterator.hasNext()) {
- Entry entry = (Entry) iterator.next();
- HandleEntry handleEntry = (HandleEntry) entry.getValue();
- if (handleEntry.isExpired()) {
- needsDeleting.add(entry.getKey());
- }
- }
- // release the lock to be friendly
- Iterator deleteIterator = needsDeleting.iterator();
- while (deleteIterator.hasNext()) {
- synchronized (handleEntries) {
- log.debug("Expiring an Attribute Query Handle from the memory cache.");
- handleEntries.remove(deleteIterator.next());
- }
- }
- }
- sleep(60 * 1000); // one minute
- } catch (InterruptedException e) {
- log.debug("Memory-based shib handle cache cleanup interrupted.");
- }
- }
- }
- }
-
-}
\ No newline at end of file
+++ /dev/null
-
-package edu.internet2.middleware.shibboleth.common.provider;
-
-import java.security.cert.X509CRL;
-import java.security.cert.X509Certificate;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.NoSuchElementException;
-import java.util.Set;
-
-import javax.xml.namespace.QName;
-
-import org.apache.log4j.Logger;
-import org.opensaml.saml2.common.Extensions;
-import org.opensaml.saml2.metadata.EntitiesDescriptor;
-import org.opensaml.saml2.metadata.EntityDescriptor;
-import org.opensaml.saml2.metadata.RoleDescriptor;
-import org.opensaml.security.TrustEngine;
-import org.opensaml.security.X509EntityCredential;
-import org.opensaml.security.impl.AbstractPKIXTrustEngine;
-import org.opensaml.security.impl.InlinePKIKeyTrustEngine;
-import org.opensaml.xml.ElementProxy;
-import org.opensaml.xml.XMLObject;
-import org.opensaml.xml.signature.KeyInfo;
-
-/**
- * <code>TrustEngine</code> implementation that first attempts to do standard SAML2 inline key validation and then
- * falls back on PKIX validation against key authorities included in shibboleth-specific extensions to SAML 2 metadata.
- *
- * @author Walter Hoehn
- */
-public class ShibbolethTrustEngine extends InlinePKIKeyTrustEngine implements TrustEngine<X509EntityCredential> {
-
- private static Logger log = Logger.getLogger(ShibbolethTrustEngine.class.getName());
- private static final String KEY_AUTHORITY_LOCAL_NAME = "KeyAuthority";
- private static final String CUSTOM_METADATA_NS = "urn:mace:shibboleth:metadata:1.0";
- private static final QName KEY_AUTHORITY = new QName(CUSTOM_METADATA_NS, KEY_AUTHORITY_LOCAL_NAME);
-
- @Override
- public boolean validate(X509EntityCredential entityCredential, RoleDescriptor descriptor) {
-
- // If we can successfully validate with an inline key, that's fine
- boolean defaultValidation = super.validate(entityCredential, descriptor);
- if (defaultValidation == true) { return true; }
-
- // Make sure we have the data we need
- if (descriptor == null || entityCredential == null) {
- log.error("Appropriate data was not supplied for trust evaluation.");
- return false;
- }
-
- // If not, try PKIX validation against the shib-custom metadata extensions
- if (descriptor.getParent() == null || !(descriptor.getParent() instanceof EntityDescriptor)) {
- log.debug("Inline validation was unsuccessful. Unable to attempt PKIX validation "
- + "because we don't have a complete metadata tree.");
- return false;
-
- } else {
- log.debug("Inline validation was unsuccessful. Attmping PKIX...");
- boolean pkixValid = new ShibbolethPKIXEngine((EntityDescriptor) descriptor.getParent()).validate(
- entityCredential, descriptor);
- if (pkixValid) {
- log.debug("PKIX validation was successful.");
- } else {
- log.debug("PKIX validation was unsuccessful.");
- }
- return pkixValid;
- }
- }
-
- /**
- * Pulls <code>PKIXValidationInformation</code> out of Shibboleth-specific metadata extensions and runs the
- * results against OpenSAML's PKIX trust engine. Recurses backwards through the metadata tree, attempting PKIX
- * validation at each level that contains a <KeyAuthority/> element. Metadata is evaluated in a lazy fashion.
- */
- private class ShibbolethPKIXEngine extends AbstractPKIXTrustEngine implements TrustEngine<X509EntityCredential> {
-
- EntityDescriptor entity;
-
- private ShibbolethPKIXEngine(EntityDescriptor entity) {
-
- this.entity = entity;
- }
-
- @Override
- protected Iterator<PKIXValidationInformation> getValidationInformation(RoleDescriptor descriptor) {
-
- return new ShibPKIXMetadata(entity);
- }
-
- private class ShibPKIXMetadata implements Iterator<PKIXValidationInformation> {
-
- private ExtensionPoint currentExtensionPointRoot;
-
- private ShibPKIXMetadata(EntityDescriptor entity) {
-
- currentExtensionPointRoot = new ExtensionPoint(entity);
- }
-
- public boolean hasNext() {
-
- return (getNextKeyAuthority(currentExtensionPointRoot, false) != null);
- }
-
- public PKIXValidationInformation next() {
-
- // Construct PKIX validation information from Shib metadata
- ElementProxy keyAuthority = getNextKeyAuthority(currentExtensionPointRoot, true);
- if (keyAuthority == null) { throw new NoSuchElementException(); }
-
- return convertMetadatatoValidationInfo(keyAuthority);
-
- }
-
- public void remove() {
-
- throw new UnsupportedOperationException();
- }
-
- private PKIXValidationInformation convertMetadatatoValidationInfo(ElementProxy keyAuthority) {
-
- // Find the verification depth for all anchors in this set
- int verifyDepth = 1;
- String rawVerifyDepth = keyAuthority.getUnknownAttributes().get(new QName("VerifyDepth"));
- if (rawVerifyDepth != null && !rawVerifyDepth.equals("")) {
- try {
- verifyDepth = Integer.parseInt(rawVerifyDepth);
- } catch (NumberFormatException nfe) {
- log.error("<KeyAuthority/> attribute (VerifyDepth) is not an "
- + "integer, defaulting to most strict depth of (1).");
- verifyDepth = 1;
- }
- }
-
- // Find all trust anchors and revocation lists in the KeyInfo
- Set<X509Certificate> trustAnchors = new HashSet<X509Certificate>();
- Set<X509CRL> revocationLists = new HashSet<X509CRL>();
- for (XMLObject subExtension : keyAuthority.getUnknownXMLObjects()) {
- if (subExtension instanceof KeyInfo) {
- trustAnchors.addAll(((KeyInfo) subExtension).getCertificates());
- revocationLists.addAll(((KeyInfo) subExtension).getCRLs());
- }
- }
-
- log.debug("Found Shibboleth Key Authority Metadata: Verification depth: " + verifyDepth
- + " Trust Anchors: " + trustAnchors.size() + " Revocation Lists: " + revocationLists.size()
- + ".");
- return new PKIXValidationInformation(verifyDepth, trustAnchors, revocationLists);
- }
-
- private ElementProxy getNextKeyAuthority(ExtensionPoint extensionPoint, boolean consume) {
-
- if (extensionPoint == null) { return null; } // Can't recurse further
-
- Extensions extensions = extensionPoint.getExtensions();
-
- // Check this descriptor for a key authority
- // The complication is that a particular descriptor can have more than one key authority, which is why
- // we need this "consumedIndex" business to keep track of which ones we've processed so far
- if (extensions != null) {
- List<XMLObject> xmlObjects = extensions.getUnknownXMLObjects();
- for (int i = extensionPoint.consumedIndex; i < xmlObjects.size(); i++) {
-
- if (xmlObjects.get(i).getElementQName().equals(KEY_AUTHORITY)
- && xmlObjects.get(i) instanceof ElementProxy) {
- log.debug("Found Key Authority element in metadata.");
- if (consume && extensionPoint.consumedIndex == xmlObjects.size()) {
- currentExtensionPointRoot = new ExtensionPoint(extensionPoint.getParent());
-
- } else if (consume) {
- currentExtensionPointRoot = extensionPoint;
- extensionPoint.consumedIndex = i + 1;
- }
- return (ElementProxy) xmlObjects.get(i);
- }
- }
- }
-
- // If we don't find anything, recurse back through the parentso
- if (extensionPoint.getParent() != null) { return getNextKeyAuthority(new ExtensionPoint(extensionPoint
- .getParent()), consume); }
-
- return null;
- }
-
- class ExtensionPoint {
-
- private EntityDescriptor entity;
- private EntitiesDescriptor entities;
- int consumedIndex = 0;
-
- private ExtensionPoint(EntityDescriptor entity) {
-
- this.entity = entity;
- }
-
- private ExtensionPoint(EntitiesDescriptor entities) {
-
- this.entities = entities;
- }
-
- private Extensions getExtensions() {
-
- if (entity != null) {
- return entity.getExtensions();
- } else if (entities != null) {
- return entities.getExtensions();
- } else {
- return null;
- }
- }
-
- private EntitiesDescriptor getParent() {
-
- if (entity != null && entity.getParent() instanceof EntitiesDescriptor) {
- return (EntitiesDescriptor) entity.getParent();
- } else if (entities != null && entities.getParent() instanceof EntitiesDescriptor) {
- return (EntitiesDescriptor) entities.getParent();
- } else {
- return null;
- }
- }
-
- }
-
- }
- }
-}
+++ /dev/null
-/*
- * Copyright [2005] [University Corporation for Advanced Internet Development, Inc.] Licensed 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 edu.internet2.middleware.shibboleth.common.provider;
-
-import java.security.Principal;
-
-import org.apache.log4j.Logger;
-import org.opensaml.SAMLException;
-import org.opensaml.SAMLNameIdentifier;
-import org.w3c.dom.Element;
-
-import edu.internet2.middleware.shibboleth.common.IdentityProvider;
-import edu.internet2.middleware.shibboleth.common.InvalidNameIdentifierException;
-import edu.internet2.middleware.shibboleth.common.LocalPrincipal;
-import edu.internet2.middleware.shibboleth.common.NameIdentifierMappingException;
-import edu.internet2.middleware.shibboleth.common.ServiceProvider;
-
-/**
- * <code>NameIdentifierMapping</code> implementation for sending User Principal Names as referenced in "WS-Federation:
- * Passive Requestor Interoperability Profile". Should allow for basic interoperability with ADFS. IdPs that service
- * multiple account domains will need a slightly more complex implementation.
- *
- * @author Walter Hoehn
- */
-public class UPNNameIdentifierMapping extends BaseNameIdentifierMapping {
-
- private static Logger log = Logger.getLogger(UPNNameIdentifierMapping.class.getName());
- private String scope;
-
- public UPNNameIdentifierMapping(Element config) throws NameIdentifierMappingException {
-
- super(config);
-
- scope = config.getAttribute("scope");
- if (scope == null || scope.equals("")) {
- log.error("No (scope) attribute specified.");
- throw new NameIdentifierMappingException(
- "Unable to load UPN Name Identifier Mapping. A UPN scope must be specified.");
- }
- }
-
- public Principal getPrincipal(SAMLNameIdentifier nameId, ServiceProvider sProv, IdentityProvider idProv)
- throws NameIdentifierMappingException, InvalidNameIdentifierException {
-
- String[] splitName = nameId.getName().split("@");
-
- if (splitName == null || splitName.length < 2) {
- log.error("Improper UPN formatting. Unable to distinguish local principal from scope.");
- throw new InvalidNameIdentifierException("Name Identifier does not contain a valid UPN.", null);
- }
- if (splitName[1] == null || (!splitName[1].equals(scope))) {
- log.error("Invalid UPN scope. Expected (" + scope + "), but received (" + splitName[1] + ").");
- throw new InvalidNameIdentifierException("Name Identifier does not contain a valid UPN.", null);
- }
- if (splitName[0] == null || splitName[0].equals("")) {
- log.error("Improper UPN formatting. Unable to parse local principal.");
- throw new InvalidNameIdentifierException("Name Identifier does not contain a valid UPN.", null);
- }
-
- return new LocalPrincipal(splitName[0]);
- }
-
- public SAMLNameIdentifier getNameIdentifier(LocalPrincipal principal, ServiceProvider sProv, IdentityProvider idProv)
- throws NameIdentifierMappingException {
-
- if (principal == null) {
- log.error("A principal must be supplied for Name Identifier creation.");
- throw new IllegalArgumentException("A principal must be supplied for Name Identifier creation.");
- }
-
- try {
- SAMLNameIdentifier nameid = SAMLNameIdentifier.getInstance(getNameIdentifierFormat().toString());
- nameid.setName(principal.getName() + "@" + scope);
- nameid.setNameQualifier(idProv.getProviderId());
- return nameid;
- } catch (SAMLException e) {
- throw new NameIdentifierMappingException("Unable to generate Name Identifier: " + e);
- }
- }
-}
\ No newline at end of file
+++ /dev/null
-/*
- * Copyright [2005] [University Corporation for Advanced Internet Development, Inc.]
- *
- * Licensed 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 edu.internet2.middleware.shibboleth.common.provider;
-
-import java.security.Principal;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import java.util.regex.PatternSyntaxException;
-
-import javax.xml.namespace.QName;
-
-import org.apache.log4j.Logger;
-import org.opensaml.SAMLException;
-import org.opensaml.SAMLNameIdentifier;
-import org.w3c.dom.Element;
-
-import edu.internet2.middleware.shibboleth.common.IdentityProvider;
-import edu.internet2.middleware.shibboleth.common.InvalidNameIdentifierException;
-import edu.internet2.middleware.shibboleth.common.LocalPrincipal;
-import edu.internet2.middleware.shibboleth.common.NameIdentifierMapping;
-import edu.internet2.middleware.shibboleth.common.NameIdentifierMappingException;
-import edu.internet2.middleware.shibboleth.common.ServiceProvider;
-
-/**
- * <code>NameIdentifierMapping</code> implementation that translates principal names to E-Auth compliant
- * X509SubjectNames.
- *
- * @author Walter Hoehn
- */
-public class X509SubjectNameNameIdentifierMapping extends BaseNameIdentifierMapping implements NameIdentifierMapping {
-
- private static Logger log = Logger.getLogger(X509SubjectNameNameIdentifierMapping.class.getName());
- private String regexTemplate = ".*uid=([^,/]+).*";
- private Pattern regex;
- private String qualifier;
- private String internalNameContext;
- private QName[] errorCodes = new QName[0];
-
- public X509SubjectNameNameIdentifierMapping(Element config) throws NameIdentifierMappingException {
-
- super(config);
-
- String rawRegex = ((Element) config).getAttribute("regex");
- if (rawRegex != null && !rawRegex.equals("")) {
- try {
- regex = Pattern.compile(rawRegex);
- } catch (PatternSyntaxException e) {
- log.error("Supplied (regex) attribute is not a valid regular expressions. Using default value.");
- regex = Pattern.compile(regexTemplate);
- }
- } else {
- regex = Pattern.compile(regexTemplate);
- }
-
- qualifier = ((Element) config).getAttribute("qualifier");
- if (qualifier == null || qualifier.equals("")) {
- log.error("The X509SubjectName NameMapping requires a (qualifier) attribute.");
- throw new NameIdentifierMappingException(
- "Invalid configuration. Unable to initialize X509SubjectName Mapping.");
- }
-
- internalNameContext = ((Element) config).getAttribute("internalNameContext");
- if (internalNameContext == null || internalNameContext.equals("")) {
- log.error("The X509SubjectName NameMapping requires a (internalNameContext) attribute.");
- throw new NameIdentifierMappingException(
- "Invalid configuration. Unable to initialize X509SubjectName Mapping.");
- }
- }
-
- /*
- * (non-Javadoc)
- *
- * @see edu.internet2.middleware.shibboleth.common.NameIdentifierMapping#getPrincipal(org.opensaml.SAMLNameIdentifier,
- * edu.internet2.middleware.shibboleth.common.ServiceProvider,
- * edu.internet2.middleware.shibboleth.common.IdentityProvider)
- */
- public Principal getPrincipal(SAMLNameIdentifier nameId, ServiceProvider sProv, IdentityProvider idProv)
- throws NameIdentifierMappingException, InvalidNameIdentifierException {
-
- if (!nameId.getNameQualifier().equals(qualifier)) {
- log.error("The name qualifier (" + nameId.getNameQualifier()
- + ") for the referenced subject is not valid for this identity provider.");
- throw new NameIdentifierMappingException("The name qualifier (" + nameId.getNameQualifier()
- + ") for the referenced subject is not valid for this identity provider.");
- }
-
- Matcher matcher = regex.matcher(nameId.getName());
- matcher.find();
- String principal = matcher.group(1);
- if (principal == null) { throw new InvalidNameIdentifierException("Unable to map X509SubjectName ("
- + nameId.getName() + ") to a local principal.", errorCodes); }
- return new LocalPrincipal(principal);
- }
-
- /*
- * (non-Javadoc)
- *
- * @see edu.internet2.middleware.shibboleth.common.NameIdentifierMapping#getNameIdentifier(edu.internet2.middleware.shibboleth.common.LocalPrincipal,
- * edu.internet2.middleware.shibboleth.common.ServiceProvider,
- * edu.internet2.middleware.shibboleth.common.IdentityProvider)
- */
- public SAMLNameIdentifier getNameIdentifier(LocalPrincipal principal, ServiceProvider sProv, IdentityProvider idProv)
- throws NameIdentifierMappingException {
-
- try {
- SAMLNameIdentifier nameid = SAMLNameIdentifier.getInstance(getNameIdentifierFormat().toString());
- nameid.setName(internalNameContext.replaceAll("%PRINCIPAL%", principal.getName()));
- nameid.setNameQualifier(qualifier);
- return nameid;
- } catch (SAMLException e) {
- throw new NameIdentifierMappingException("Unable to generate X509 SubjectName: " + e);
- }
-
- }
-
-}
\ No newline at end of file
private AttributeResolver resolver;
private ArtifactMapper artifactMapper;
private Semaphore throttle;
- private TrustEngine<X509EntityCredential> trust = new ShibbolethTrustEngine();
+ private TrustEngine<X509Credential> trust = new ShibbolethTrustEngine();
private ChainingMetadataProvider wrappedMetadataProvider = new ChainingMetadataProvider();
GeneralProtocolSupport(IdPConfig config, Logger transactionLog, RelyingPartyMapper spMapper, ArpEngine arpEngine,
return artifactMapper;
}
- public TrustEngine<X509EntityCredential> getTrustEngine() {
+ public TrustEngine<X509Credential> getTrustEngine() {
return trust;
}
/**
* Returns an OpenSAML2 Trust Engine implementation.
*/
- public TrustEngine<X509EntityCredential> getTrustEngine();
+ public TrustEngine<X509Credential> getTrustEngine();
/**
* Returns the number of active Metadata Providers.
return wrapped.getTransactionLog();
}
- public TrustEngine<X509EntityCredential> getTrustEngine() {
+ public TrustEngine<X509Credential> getTrustEngine() {
return wrapped.getTrustEngine();
}
addr = null;
}
- Session shibSession = sessionMgr.createSession(addr,
+ Session shibSession = (Session) sessionMgr.createSession(addr,
loginContext.getUserID());
List<AuthenticationMethodInformation> authMethods =
shibSession.getAuthenticationMethods();
+++ /dev/null
-/*
- * Copyright [2005] [University Corporation for Advanced Internet Development, Inc.]
- *
- * Licensed 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 edu.internet2.middleware.shibboleth.idp.provider;
-
-import org.w3c.dom.Element;
-
-import edu.internet2.middleware.shibboleth.common.ShibbolethConfigurationException;
-import edu.internet2.middleware.shibboleth.idp.IdPProtocolHandler;
-
-/**
- * Base class for SAML2 protocol hanlders.
- *
- * @author Walter Hoehn
- */
-
-public abstract class SAML2ProtcolHandler extends BaseHandler implements IdPProtocolHandler {
-
- public SAML2ProtcolHandler(Element config) throws ShibbolethConfigurationException {
-
- super(config);
- }
-}
+++ /dev/null
-/*
- * Copyright [2005] [University Corporation for Advanced Internet Development, Inc.]
- *
- * Licensed 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 edu.internet2.middleware.shibboleth.idp.provider;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.w3c.dom.Element;
-
-import edu.internet2.middleware.shibboleth.common.ShibbolethConfigurationException;
-import edu.internet2.middleware.shibboleth.idp.IdPProtocolHandler;
-import edu.internet2.middleware.shibboleth.idp.IdPProtocolSupport;
-import edu.internet2.middleware.shibboleth.idp.RequestHandlingException;
-
-/**
- * @author Walter Hoehn
- */
-public class SAML2_ArtifactResolutionHandler extends SAML2ProtcolHandler implements IdPProtocolHandler {
-
- public SAML2_ArtifactResolutionHandler(Element config) throws ShibbolethConfigurationException {
-
- super(config);
- }
-
- public String getHandlerName() {
-
- return "SAML v2 Artifact Resolution";
- }
-
- public void processRequest(HttpServletRequest request, HttpServletResponse response, IdPProtocolSupport support)
- throws RequestHandlingException, ServletException {
-
- // TODO implement
- // TODO support SOAP
- }
-}
+++ /dev/null
-/*
- * Copyright [2005] [University Corporation for Advanced Internet Development, Inc.]
- *
- * Licensed 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 edu.internet2.middleware.shibboleth.idp.provider;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.w3c.dom.Element;
-
-import edu.internet2.middleware.shibboleth.common.ShibbolethConfigurationException;
-import edu.internet2.middleware.shibboleth.idp.IdPProtocolHandler;
-import edu.internet2.middleware.shibboleth.idp.IdPProtocolSupport;
-import edu.internet2.middleware.shibboleth.idp.RequestHandlingException;
-
-/**
- * @author Walter Hoehn
- */
-public class SAML2_AssertionIDRequestHandler extends SAML2ProtcolHandler implements IdPProtocolHandler {
-
- public SAML2_AssertionIDRequestHandler(Element config) throws ShibbolethConfigurationException {
-
- super(config);
- }
-
- public String getHandlerName() {
-
- return "SAML v2 Enhanced Client/Proxy";
- }
-
- public void processRequest(HttpServletRequest request, HttpServletResponse response, IdPProtocolSupport support)
- throws RequestHandlingException, ServletException {
-
- // TODO implement
- // TODO support SOAP
- // TODO support URI binding
- }
-
-}
+++ /dev/null
-/*
- * Copyright [2005] [University Corporation for Advanced Internet Development, Inc.]
- *
- * Licensed 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 edu.internet2.middleware.shibboleth.idp.provider;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.w3c.dom.Element;
-
-import edu.internet2.middleware.shibboleth.common.ShibbolethConfigurationException;
-import edu.internet2.middleware.shibboleth.idp.IdPProtocolHandler;
-import edu.internet2.middleware.shibboleth.idp.IdPProtocolSupport;
-import edu.internet2.middleware.shibboleth.idp.RequestHandlingException;
-
-/**
- * @author Walter Hoehn
- */
-public class SAML2_AttributeQueryHandler extends SAML2ProtcolHandler implements IdPProtocolHandler {
-
- public SAML2_AttributeQueryHandler(Element config) throws ShibbolethConfigurationException {
-
- super(config);
- }
-
- public String getHandlerName() {
-
- return "SAML v2 Assertion ID Request";
- }
-
- public void processRequest(HttpServletRequest request, HttpServletResponse response, IdPProtocolSupport support)
- throws RequestHandlingException, ServletException {
-
- // TODO implement
- // TODO support SOAP
- }
-
-}
+++ /dev/null
-/*
- * Copyright [2005] [University Corporation for Advanced Internet Development, Inc.]
- *
- * Licensed 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 edu.internet2.middleware.shibboleth.idp.provider;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.w3c.dom.Element;
-
-import edu.internet2.middleware.shibboleth.common.ShibbolethConfigurationException;
-import edu.internet2.middleware.shibboleth.idp.IdPProtocolHandler;
-import edu.internet2.middleware.shibboleth.idp.IdPProtocolSupport;
-import edu.internet2.middleware.shibboleth.idp.RequestHandlingException;
-
-/**
- * @author Walter Hoehn
- */
-public class SAML2_AuthNQueryHandler extends SAML2ProtcolHandler implements IdPProtocolHandler {
-
- public SAML2_AuthNQueryHandler(Element config) throws ShibbolethConfigurationException {
-
- super(config);
- }
-
- public String getHandlerName() {
-
- return "SAML v2 AuthN Query";
- }
-
- public void processRequest(HttpServletRequest request, HttpServletResponse response, IdPProtocolSupport support)
- throws RequestHandlingException, ServletException {
-
- // TODO implement
- // TODO support SOAP
-
- }
-
-}
+++ /dev/null
-/*
- * Copyright [2005] [University Corporation for Advanced Internet Development, Inc.]
- *
- * Licensed 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 edu.internet2.middleware.shibboleth.idp.provider;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.w3c.dom.Element;
-
-import edu.internet2.middleware.shibboleth.common.ShibbolethConfigurationException;
-import edu.internet2.middleware.shibboleth.idp.IdPProtocolHandler;
-import edu.internet2.middleware.shibboleth.idp.IdPProtocolSupport;
-import edu.internet2.middleware.shibboleth.idp.RequestHandlingException;
-
-/**
- * @author Walter Hoehn
- */
-public class SAML2_AuthnRequestHandler extends SAML2ProtcolHandler implements IdPProtocolHandler {
-
- public SAML2_AuthnRequestHandler(Element config) throws ShibbolethConfigurationException {
-
- super(config);
- }
-
- public String getHandlerName() {
-
- return "SAML v2 Authn Request";
- }
-
- public void processRequest(HttpServletRequest request, HttpServletResponse response, IdPProtocolSupport support)
- throws RequestHandlingException, ServletException {
-
- // TODO implement
- // TODO support redirect
- // TODO support artifact
- // TODO support POST
-
- }
-
-}
+++ /dev/null
-/*
- * Copyright [2005] [University Corporation for Advanced Internet Development, Inc.]
- *
- * Licensed 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 edu.internet2.middleware.shibboleth.idp.provider;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.w3c.dom.Element;
-
-import edu.internet2.middleware.shibboleth.common.ShibbolethConfigurationException;
-import edu.internet2.middleware.shibboleth.idp.IdPProtocolHandler;
-import edu.internet2.middleware.shibboleth.idp.IdPProtocolSupport;
-import edu.internet2.middleware.shibboleth.idp.RequestHandlingException;
-
-/**
- * @author Walter Hoehn
- */
-public class SAML2_ECPHandler extends SAML2ProtcolHandler implements IdPProtocolHandler {
-
- public SAML2_ECPHandler(Element config) throws ShibbolethConfigurationException {
-
- super(config);
- }
-
- public String getHandlerName() {
-
- return "SAML v2 Enhanced Client/Proxy";
- }
-
- public void processRequest(HttpServletRequest request, HttpServletResponse response, IdPProtocolSupport support)
- throws RequestHandlingException, ServletException {
-
- // TODO implement
- // TODO support PAOS
-
- }
-
-}
+++ /dev/null
-/*
- * Copyright [2005] [University Corporation for Advanced Internet Development, Inc.]
- *
- * Licensed 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 edu.internet2.middleware.shibboleth.idp.provider;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.w3c.dom.Element;
-
-import edu.internet2.middleware.shibboleth.common.ShibbolethConfigurationException;
-import edu.internet2.middleware.shibboleth.idp.IdPProtocolHandler;
-import edu.internet2.middleware.shibboleth.idp.IdPProtocolSupport;
-import edu.internet2.middleware.shibboleth.idp.RequestHandlingException;
-
-/**
- * @author Walter Hoehn
- */
-public class SAML2_LogoutRequestHandler extends SAML2ProtcolHandler implements IdPProtocolHandler {
-
- public SAML2_LogoutRequestHandler(Element config) throws ShibbolethConfigurationException {
-
- super(config);
- }
-
- public String getHandlerName() {
-
- return "SAML v2 Logout Request";
- }
-
- public void processRequest(HttpServletRequest request, HttpServletResponse response, IdPProtocolSupport support)
- throws RequestHandlingException, ServletException {
-
- // TODO implement
- // TODO support redirect
- // TODO support SOAP
-
- }
-
-}
+++ /dev/null
-/*
- * Copyright [2005] [University Corporation for Advanced Internet Development, Inc.]
- *
- * Licensed 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 edu.internet2.middleware.shibboleth.idp.provider;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.w3c.dom.Element;
-
-import edu.internet2.middleware.shibboleth.common.ShibbolethConfigurationException;
-import edu.internet2.middleware.shibboleth.idp.IdPProtocolHandler;
-import edu.internet2.middleware.shibboleth.idp.IdPProtocolSupport;
-import edu.internet2.middleware.shibboleth.idp.RequestHandlingException;
-
-/**
- * @author Walter Hoehn
- */
-public class SAML2_ManageNameIDRequestHandler extends SAML2ProtcolHandler implements IdPProtocolHandler {
-
- public SAML2_ManageNameIDRequestHandler(Element config) throws ShibbolethConfigurationException {
-
- super(config);
- }
-
- public String getHandlerName() {
-
- return "SAML v2 Manage NameID Request";
- }
-
- public void processRequest(HttpServletRequest request, HttpServletResponse response, IdPProtocolSupport support)
- throws RequestHandlingException, ServletException {
-
- // TODO implement
- // TODO support redirect
- // TODO SOAP
- }
-
-}
+++ /dev/null
-/*
- * Copyright [2005] [University Corporation for Advanced Internet Development, Inc.]
- *
- * Licensed 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&nb