import sun.misc.BASE64Encoder;
import edu.internet2.middleware.shibboleth.aa.attrresolv.AttributeDefinitionPlugIn;
+import edu.internet2.middleware.shibboleth.aa.attrresolv.AttributeResolver;
import edu.internet2.middleware.shibboleth.aa.attrresolv.Dependencies;
import edu.internet2.middleware.shibboleth.aa.attrresolv.ResolutionPlugInException;
import edu.internet2.middleware.shibboleth.aa.attrresolv.ResolverAttribute;
public class PersistentIDAttributeDefinition extends BaseAttributeDefinition implements AttributeDefinitionPlugIn {
private static Logger log = Logger.getLogger(PersistentIDAttributeDefinition.class.getName());
- protected byte salt[];
- protected String localPersistentId = null;
+ protected byte salt[];
+ protected String localPersistentId = null;
+ protected String scope;
/**
* Constructor for PersistentIDAttributeDefinition. Creates a PlugIn based on configuration
public PersistentIDAttributeDefinition(Element e) throws ResolutionPlugInException {
super(e);
- localPersistentId = e.getAttributeNS(null, "sourceName");
+ localPersistentId = e.getAttributeNS(null, "sourceName");
- //Make sure we understand how to resolve the local persistent ID for the principal.
- if (localPersistentId != null && localPersistentId.length() > 0) {
- if (connectorDependencyIds.size() != 1 || !attributeDependencyIds.isEmpty()) {
- log.error("Can't specify the sourceName attribute without a single connector dependency.");
- throw new ResolutionPlugInException("Failed to initialize Attribute Definition PlugIn.");
- }
- }
- else if (!connectorDependencyIds.isEmpty()) {
- log.error("Can't specify a connector dependency without supplying the sourceName attribute.");
- throw new ResolutionPlugInException("Failed to initialize Attribute Definition PlugIn.");
- }
- else if (attributeDependencyIds.size() > 1) {
- log.error("Can't specify more than one attribute dependency, this is ambiguous.");
- throw new ResolutionPlugInException("Failed to initialize Attribute Definition PlugIn.");
- }
-
- //Salt can be either embedded in the element or pulled out of a keystore.
- NodeList salts = e.getElementsByTagNameNS(null, "Salt");
- if (salts == null || salts.getLength() != 1) {
- log.error("Missing <Salt> from attribute definition configuration.");
- throw new ResolutionPlugInException("Failed to initialize Attribute Definition PlugIn.");
- }
-
- Element salt = (Element)salts.item(0);
- Node child = salt.getFirstChild();
- if (child != null && child.getNodeType()==Node.TEXT_NODE &&
- child.getNodeValue() != null && child.getNodeValue().length() >= 16)
- this.salt = child.getNodeValue().getBytes();
- else {
- String ksPath = salt.getAttributeNS(null, "keyStorePath");
- String keyAlias = salt.getAttributeNS(null, "keyStoreKeyAlias");
- String ksPass = salt.getAttributeNS(null, "keyStorePassword");
- String keyPass = salt.getAttributeNS(null, "keyStoreKeyPassword");
-
- if (ksPath == null || ksPath.length() == 0 ||
- keyAlias == null || keyAlias.length() == 0 ||
- ksPass == null || ksPass.length() == 0 ||
- keyPass == null || keyPass.length() == 0) {
+ //Make sure we understand how to resolve the local persistent ID for the principal.
+ if (localPersistentId != null && localPersistentId.length() > 0) {
+ if (connectorDependencyIds.size() != 1 || !attributeDependencyIds.isEmpty()) {
+ log.error("Can't specify the sourceName attribute without a single connector dependency.");
+ throw new ResolutionPlugInException("Failed to initialize Attribute Definition PlugIn.");
+ }
+ } else if (!connectorDependencyIds.isEmpty()) {
+ log.error("Can't specify a connector dependency without supplying the sourceName attribute.");
+ throw new ResolutionPlugInException("Failed to initialize Attribute Definition PlugIn.");
+ } else if (attributeDependencyIds.size() > 1) {
+ log.error("Can't specify more than one attribute dependency, this is ambiguous.");
+ throw new ResolutionPlugInException("Failed to initialize Attribute Definition PlugIn.");
+ }
+
+ //Grab user specified scope
+ scope = e.getAttribute("scope");
+ if (scope == null || scope.equals("")) {
+ log.error("Attribute \"scope\" required to configure plugin.");
+ throw new ResolutionPlugInException("Failed to initialize Attribute Definition PlugIn.");
+ }
+
+ //Salt can be either embedded in the element or pulled out of a keystore.
+ NodeList salts = e.getElementsByTagNameNS(AttributeResolver.resolverNamespace, "Salt");
+ if (salts == null || salts.getLength() != 1) {
+ log.error("Missing <Salt> from attribute definition configuration.");
+ throw new ResolutionPlugInException("Failed to initialize Attribute Definition PlugIn.");
+ }
+
+ Element salt = (Element) salts.item(0);
+ Node child = salt.getFirstChild();
+ if (child != null
+ && child.getNodeType() == Node.TEXT_NODE
+ && child.getNodeValue() != null
+ && child.getNodeValue().length() >= 16)
+ this.salt = child.getNodeValue().getBytes();
+ else {
+ String ksPath = salt.getAttributeNS(null, "keyStorePath");
+ String keyAlias = salt.getAttributeNS(null, "keyStoreKeyAlias");
+ String ksPass = salt.getAttributeNS(null, "keyStorePassword");
+ String keyPass = salt.getAttributeNS(null, "keyStoreKeyPassword");
+
+ if (ksPath == null
+ || ksPath.length() == 0
+ || keyAlias == null
+ || keyAlias.length() == 0
+ || ksPass == null
+ || ksPass.length() == 0
+ || keyPass == null
+ || keyPass.length() == 0) {
+
+ log.error("Missing <Salt> keyStore attributes from attribute definition configuration.");
+ throw new ResolutionPlugInException("Failed to initialize Attribute Definition PlugIn.");
+ }
- log.error("Missing <Salt> keyStore attributes from attribute definition configuration.");
- throw new ResolutionPlugInException("Failed to initialize Attribute Definition PlugIn.");
- }
+ try {
+ KeyStore keyStore = KeyStore.getInstance("JCEKS");
- try {
- KeyStore keyStore = KeyStore.getInstance("JCEKS");
-
- keyStore.load(new ShibResource(ksPath, this.getClass()).getInputStream(), ksPass.toCharArray());
- SecretKey secret = (SecretKey)keyStore.getKey(keyAlias, keyPass.toCharArray());
-
- if (usingDefaultSecret()) {
- log.warn(
- "You are running the PersistentIDAttributeDefinition PlugIn with the default secret key as a salt. This is UNSAFE! Please change "
- + "this configuration and restart the origin.");
- }
- this.salt = secret.getEncoded();
-
- }
- catch (KeyStoreException ex) {
- log.error(
- "An error occurred while loading the java keystore. Unable to initialize Attribute Definition PlugIn: "
- + ex);
- throw new ResolutionPlugInException("An error occurred while loading the java keystore. Unable to initialize Attribute Definition PlugIn.");
- }
- catch (CertificateException ex) {
- log.error(
- "The java keystore contained corrupted data. Unable to initialize Attribute Definition PlugIn: " + ex);
- throw new ResolutionPlugInException("The java keystore contained corrupted data. Unable to initialize Attribute Definition PlugIn.");
- }
- catch (NoSuchAlgorithmException ex) {
- log.error(
- "Appropriate JCE provider not found in the java environment. Unable to initialize Attribute Definition PlugIn: "
- + ex);
- throw new ResolutionPlugInException("Appropriate JCE provider not found in the java environment. Unable to initialize Attribute Definition PlugIn.");
- }
- catch (IOException ex) {
- log.error(
- "An error accessing while loading the java keystore. Unable to initialize Attribute Definition PlugIn: "
- + ex);
- throw new ResolutionPlugInException("An error occurred while accessing the java keystore. Unable to initialize Attribute Definition PlugIn.");
- }
- catch (UnrecoverableKeyException ex) {
- log.error(
- "Secret could not be loaded from the java keystore. Verify that the alias and password are correct: "
- + ex);
- throw new ResolutionPlugInException("Secret could not be loaded from the java keystore. Verify that the alias and password are correct. ");
- }
- }
+ keyStore.load(new ShibResource(ksPath, this.getClass()).getInputStream(), ksPass.toCharArray());
+ SecretKey secret = (SecretKey) keyStore.getKey(keyAlias, keyPass.toCharArray());
+
+ if (usingDefaultSecret()) {
+ log.warn(
+ "You are running the PersistentIDAttributeDefinition PlugIn with the default secret key as a salt. This is UNSAFE! Please change "
+ + "this configuration and restart the origin.");
+ }
+ this.salt = secret.getEncoded();
+
+ } catch (KeyStoreException ex) {
+ log.error(
+ "An error occurred while loading the java keystore. Unable to initialize Attribute Definition PlugIn: "
+ + ex);
+ throw new ResolutionPlugInException("An error occurred while loading the java keystore. Unable to initialize Attribute Definition PlugIn.");
+ } catch (CertificateException ex) {
+ log.error(
+ "The java keystore contained corrupted data. Unable to initialize Attribute Definition PlugIn: "
+ + ex);
+ throw new ResolutionPlugInException("The java keystore contained corrupted data. Unable to initialize Attribute Definition PlugIn.");
+ } catch (NoSuchAlgorithmException ex) {
+ log.error(
+ "Appropriate JCE provider not found in the java environment. Unable to initialize Attribute Definition PlugIn: "
+ + ex);
+ throw new ResolutionPlugInException("Appropriate JCE provider not found in the java environment. Unable to initialize Attribute Definition PlugIn.");
+ } catch (IOException ex) {
+ log.error(
+ "An error accessing while loading the java keystore. Unable to initialize Attribute Definition PlugIn: "
+ + ex);
+ throw new ResolutionPlugInException("An error occurred while accessing the java keystore. Unable to initialize Attribute Definition PlugIn.");
+ } catch (UnrecoverableKeyException ex) {
+ log.error(
+ "Secret could not be loaded from the java keystore. Verify that the alias and password are correct: "
+ + ex);
+ throw new ResolutionPlugInException("Secret could not be loaded from the java keystore. Verify that the alias and password are correct. ");
+ }
+ }
}
/**
public void resolve(ResolverAttribute attribute, Principal principal, String requester, Dependencies depends)
throws ResolutionPlugInException {
log.debug("Resolving attribute: (" + getId() + ")");
- String localId = null;
+ String localId = null;
- //Resolve the correct local persistent identifier.
- if (!attributeDependencyIds.isEmpty()) {
- ResolverAttribute dep = depends.getAttributeResolution((String) attributeDependencyIds.iterator().next());
- if (dep != null) {
- Iterator vals = dep.getValues();
- if (vals.hasNext()) {
- log.debug("Found persistent ID value for attribute (" + getId() + ").");
- localId = (String)vals.next();
- if (vals.hasNext()) {
- log.error("An attribute dependency of attribute (" + getId() + ") returned multiple values, expecting only one.");
- return;
- }
- }
- else {
- log.error("An attribute dependency of attribute (" + getId() + ") returned no values, expecting one.");
- return;
- }
- }
- else {
- log.error(
- "An attribute dependency of attribute (" + getId() + ") was not included in the dependency chain.");
- return;
- }
- }
- else if (!connectorDependencyIds.isEmpty()) {
- Attributes attrs = depends.getConnectorResolution((String) connectorDependencyIds.iterator().next());
- if (attrs != null) {
- Attribute attr = attrs.get(localPersistentId);
- if (attr != null) {
- if (attr.size() != 1) {
- log.error("An attribute dependency of attribute (" + getId() + ") returned " + attr.size() + " values, expecting only one.");
- }
- else {
- try
- {
- localId = (String)attr.get();
- log.debug("Found persistent ID value for attribute (" + getId() + ").");
- }
- catch (NamingException e)
- {
- log.error("A connector dependency of attribute (" + getId() + ") threw an exception: " + e);
- return;
- }
- }
- }
- }
- else {
- log.error(
- "A connector dependency of attribute (" + getId() + ") did not return any attributes.");
- return;
- }
+ //Resolve the correct local persistent identifier.
+ if (!attributeDependencyIds.isEmpty()) {
+ ResolverAttribute dep = depends.getAttributeResolution((String) attributeDependencyIds.iterator().next());
+ if (dep != null) {
+ Iterator vals = dep.getValues();
+ if (vals.hasNext()) {
+ log.debug("Found persistent ID value for attribute (" + getId() + ").");
+ localId = (String) vals.next();
+ if (vals.hasNext()) {
+ log.error(
+ "An attribute dependency of attribute ("
+ + getId()
+ + ") returned multiple values, expecting only one.");
+ return;
+ }
+ } else {
+ log.error(
+ "An attribute dependency of attribute (" + getId() + ") returned no values, expecting one.");
+ return;
+ }
+ } else {
+ log.error(
+ "An attribute dependency of attribute (" + getId() + ") was not included in the dependency chain.");
+ return;
+ }
+ } else if (!connectorDependencyIds.isEmpty()) {
+ Attributes attrs = depends.getConnectorResolution((String) connectorDependencyIds.iterator().next());
+ if (attrs != null) {
+ Attribute attr = attrs.get(localPersistentId);
+ if (attr != null) {
+ if (attr.size() != 1) {
+ log.error(
+ "An attribute dependency of attribute ("
+ + getId()
+ + ") returned "
+ + attr.size()
+ + " values, expecting only one.");
+ } else {
+ try {
+ localId = (String) attr.get();
+ log.debug("Found persistent ID value for attribute (" + getId() + ").");
+ } catch (NamingException e) {
+ log.error("A connector dependency of attribute (" + getId() + ") threw an exception: " + e);
+ return;
+ }
+ }
+ }
+ } else {
+ log.error("A connector dependency of attribute (" + getId() + ") did not return any attributes.");
+ return;
+ }
+ } else {
+ localId = principal.getName();
}
- else {
- localId = principal.getName();
- }
- if (lifeTime != -1) {
- attribute.setLifetime(lifeTime);
- }
+ if (lifeTime != -1) {
+ attribute.setLifetime(lifeTime);
+ }
+
+ //Hash the data together to produce the persistent ID.
+ try {
+ MessageDigest md = MessageDigest.getInstance("SHA");
+ md.update(requester.getBytes());
+ md.update((byte) '!');
+ md.update(localId.getBytes());
+ md.update((byte) '!');
+ String result = new BASE64Encoder().encode(md.digest(salt));
- //Hash the data together to produce the persistent ID.
- try
- {
- MessageDigest md = MessageDigest.getInstance("SHA");
- md.update(requester.getBytes());
- md.update((byte)'!');
- md.update(localId.getBytes());
- md.update((byte)'!');
- String result = new BASE64Encoder().encode(md.digest(salt));
-
- attribute.addValue(result.replaceAll(System.getProperty("line.separator"), ""));
- attribute.setResolved();
- }
- catch (NoSuchAlgorithmException e)
- {
- log.error("Unable to load SHA-1 hash algorithm.");
- }
+ attribute.registerValueHandler(new ScopedStringValueHandler(scope));
+ attribute.addValue(result.replaceAll(System.getProperty("line.separator"), ""));
+ attribute.setResolved();
+ } catch (NoSuchAlgorithmException e) {
+ log.error("Unable to load SHA-1 hash algorithm.");
+ }
}
- 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 };
- return Arrays.equals(defaultKey, salt);
- }
+ 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 };
+ return Arrays.equals(defaultKey, salt);
+ }
}