/* * Copyright 2001-2005 Internet2 * * 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. */ /* * File: SAMLArtifactType0001.java * */ package gov.nih.nci.cagrid.opensaml.artifact; import gov.nih.nci.cagrid.opensaml.SAMLConfig; import gov.nih.nci.cagrid.opensaml.artifact.Artifact; import gov.nih.nci.cagrid.opensaml.artifact.ArtifactParseException; import gov.nih.nci.cagrid.opensaml.artifact.SAMLArtifact; import gov.nih.nci.cagrid.opensaml.artifact.Util; import org.apache.commons.codec.binary.Base64; /** * <p>This class implements a type 0x0001 artifact as * specified by SAML V1.1.</p> * * <pre>TypeCode := 0x0001 *RemainingArtifact := SourceId AssertionHandle *SourceId := 20-byte_sequence *AssertionHandle := 20-byte_sequence</pre> * * <p>Thus a type 0x0001 artifact is of size 42 bytes * (unencoded).</p> * * <p>The <code>SourceId</code> is an arbitrary sequence * of bytes. In practice, the <code>SourceId</code> is * the SHA-1 hash of the IdP providerId.</p> * * <p>The <code>AssertionHandle</code> is a sequence * of random bytes that points to an * authentication assertion at the IdP.</p> * * @author Tom Scavo */ public class SAMLArtifactType0001 extends SAMLArtifact { /** * The type code of this <code>Artifact</code> object. */ public static final Artifact.TypeCode TYPE_CODE = new TypeCode( (byte) 0x00, (byte) 0x01 ); /** * This constructor initializes the * <code>remainingArtifact</code> property by calling * the corresponding constructor of this implementation * of <code>Artifact.RemainingArtifact</code>. * <p> * This constructor throws a <code>NullArgumentException</code> * or <code>InvalidArgumentException</code> if its argument is * null or invalid, respectively. These exceptions are unchecked. * * @param sourceId the desired source Id * of this <code>SAMLArtifactType0001</code> object * * @see SAMLArtifactType0001.RemainingArtifact * @see gov.nih.nci.cagrid.opensaml.artifact.NullArgumentException * @see gov.nih.nci.cagrid.opensaml.artifact.InvalidArgumentException */ public SAMLArtifactType0001( byte[] sourceId ) { checkIdentifierArg( sourceId ); this.typeCode = TYPE_CODE; this.remainingArtifact = new RemainingArtifact( sourceId ); } /** * This constructor initializes the * <code>remainingArtifact</code> property by calling * the corresponding constructor of this implementation * of <code>Artifact.RemainingArtifact</code>. * <p> * This constructor throws a <code>NullArgumentException</code> * or <code>InvalidArgumentException</code> if any of its * arguments are null or invalid, respectively. * These exceptions are unchecked. * * @param sourceId the desired source Id * of this <code>SAMLArtifactType0001</code> object * * @param assertionHandle the desired assertion handle * of this <code>SAMLArtifactType0001</code> object * * @see SAMLArtifactType0001.RemainingArtifact * @see gov.nih.nci.cagrid.opensaml.artifact.NullArgumentException * @see gov.nih.nci.cagrid.opensaml.artifact.InvalidArgumentException */ public SAMLArtifactType0001( byte[] sourceId, byte[] assertionHandle ) { checkIdentifierArg( sourceId ); checkHandleArg( assertionHandle ); this.typeCode = TYPE_CODE; this.remainingArtifact = new RemainingArtifact( sourceId, assertionHandle ); } /** * This constructor initializes the * <code>remainingArtifact</code> property to the * given value. * <p> * This constructor throws an (unchecked) * <code>NullArgumentException</code> if its argument is null. * * @param remainingArtifact the desired value of * the <code>remainingArtifact</code> property * of this <code>SAMLArtifactType0001</code> object * * @see SAMLArtifactType0001.RemainingArtifact * @see gov.nih.nci.cagrid.opensaml.artifact.NullArgumentException */ public SAMLArtifactType0001( Artifact.RemainingArtifact remainingArtifact ) { checkNullArg( remainingArtifact ); this.typeCode = TYPE_CODE; this.remainingArtifact = remainingArtifact; } /** * A convenience method that returns the * <code>sourceId</code> property of this implementation * of <code>Artifact.RemainingArtifact</code>. * * @return the <code>sourceId</code> property * * @see SAMLArtifactType0001.RemainingArtifact */ public byte[] getSourceId() { return ((RemainingArtifact) this.remainingArtifact).getSourceId(); } /** * A convenience method that returns the * <code>assertionHandle</code> property of this implementation * of <code>Artifact.RemainingArtifact</code>. * * @return the <code>assertionHandle</code> property * * @see SAMLArtifactType0001.RemainingArtifact */ public byte[] getAssertionHandle() { return ((RemainingArtifact) this.remainingArtifact).getAssertionHandle(); } /** * An implementation of <code>Artifact.RemainingArtifact</code> * for type 0x0001 artifacts (via extension of * <code>SAMLArtifact.RemainingArtifact</code>). * This class defines two properties * (<code>sourceId</code> and <code>assertionHandle</code>). */ public static final class RemainingArtifact extends SAMLArtifact.RemainingArtifact { private byte[] sourceId; private byte[] assertionHandle; /** * This constructor initializes a property * of this <code>RemainingArtifact</code> * object to the given value. * <p> * This constructor throws a <code>NullArgumentException</code> * or <code>InvalidArgumentException</code> if its argument is * null or invalid, respectively. These exceptions are unchecked. * * @param sourceId a source Id * * @see gov.nih.nci.cagrid.opensaml.artifact.NullArgumentException * @see gov.nih.nci.cagrid.opensaml.artifact.InvalidArgumentException */ public RemainingArtifact( byte[] sourceId ) { checkIdentifierArg( sourceId ); this.sourceId = sourceId; this.assertionHandle = SAMLConfig.instance().getDefaultIDProvider().generateRandomBytes( HANDLE_LENGTH ); } /** * This constructor initializes the properties * of this <code>RemainingArtifact</code> * object to the given values. * <p> * This constructor throws a <code>NullArgumentException</code> * or <code>InvalidArgumentException</code> if any of its * arguments are null or invalid, respectively. * These exceptions are unchecked. * * @param sourceId a source Id * @param assertionHandle an assertion handle * * @see gov.nih.nci.cagrid.opensaml.artifact.NullArgumentException * @see gov.nih.nci.cagrid.opensaml.artifact.InvalidArgumentException */ public RemainingArtifact( byte[] sourceId, byte[] assertionHandle ) { checkIdentifierArg( sourceId ); checkHandleArg( assertionHandle ); this.sourceId = sourceId; this.assertionHandle = assertionHandle; } /** * Get the <code>sourceId</code> property of this * <code>Artifact.RemainingArtifact</code> object. * * return the <code>sourceId</code> property */ public byte[] getSourceId() { return this.sourceId; } /** * Get the <code>assertionHandle</code> property of this * <code>Artifact.RemainingArtifact</code> object. * * return the <code>assertionHandle</code> property */ public byte[] getAssertionHandle() { return this.assertionHandle; } public int size() { return this.sourceId.length + this.assertionHandle.length; } public byte[] getBytes() { byte[] bytes0 = this.sourceId; byte[] bytes1 = this.assertionHandle; return Util.concat( bytes0, bytes1 ); } public int hashCode() { return this.sourceId.hashCode() & this.assertionHandle.hashCode(); } } /** * An implementation of <code>Artifact.Parser</code> * for type 0x0001 artifacts. */ public static final class Parser implements Artifact.Parser { /** * Parse the given encoded string. * * @param s the encoded string * * @return an artifact that may be cast to type * <code>SAMLArtifactType0001</code> * * @exception gov.nih.nci.cagrid.opensaml.artifact.ArtifactParseException * if the length of the decoded string is * not equal to the required length, or the * type code is incorrect * * @see org.apache.commons.codec.binary.Base64 */ public Artifact parse( String s ) throws ArtifactParseException { // check total length: byte[] bytes = Base64.decodeBase64( s.getBytes() ); int expectedLength = 2 + IDENTIFIER_LENGTH + HANDLE_LENGTH; if ( bytes.length != expectedLength ) { throw new ArtifactParseException( bytes.length, expectedLength ); } // check type code: TypeCode typeCode = new TypeCode( (byte) bytes[0], (byte) bytes[1] ); if ( ! typeCode.equals( TYPE_CODE ) ) { throw new ArtifactParseException( typeCode, TYPE_CODE ); } // create and return the artifact: byte[] sourceId = new byte[ IDENTIFIER_LENGTH ]; System.arraycopy( bytes, 2, sourceId, 0, IDENTIFIER_LENGTH ); byte[] assertionHandle = new byte[ HANDLE_LENGTH ]; System.arraycopy( bytes, 2 + IDENTIFIER_LENGTH, assertionHandle, 0, HANDLE_LENGTH ); return new SAMLArtifactType0001( sourceId, assertionHandle ); } } }