| /* |
| * Copyright 2004,2005 The Apache Software Foundation. |
| * |
| * 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 org.apache.rahas.impl; |
| |
| import org.apache.rahas.*; |
| import org.apache.rahas.TrustException; |
| import org.apache.rahas.impl.util.SignKeyHolder; |
| import org.apache.rahas.impl.util.SAMLAttributeCallback; |
| import org.apache.rahas.impl.util.SAMLCallbackHandler; |
| import org.apache.axiom.soap.SOAPEnvelope; |
| import org.apache.axiom.om.OMElement; |
| import org.apache.axiom.om.OMNode; |
| import org.apache.axiom.om.util.UUIDGenerator; |
| import org.apache.axiom.om.impl.dom.jaxp.DocumentBuilderFactoryImpl; |
| import org.apache.axis2.context.MessageContext; |
| import org.apache.axis2.description.Parameter; |
| import org.apache.ws.security.components.crypto.Crypto; |
| import org.apache.ws.security.components.crypto.CryptoFactory; |
| import org.apache.ws.security.message.WSSecEncryptedKey; |
| import org.apache.ws.security.WSConstants; |
| import org.apache.ws.security.WSSecurityException; |
| import org.apache.ws.security.util.Base64; |
| import org.apache.ws.security.util.Loader; |
| import org.apache.ws.security.util.XmlSchemaDateFormat; |
| import org.apache.xml.security.utils.EncryptionConstants; |
| import org.apache.xml.security.c14n.Canonicalizer; |
| import org.apache.xml.security.signature.XMLSignature; |
| import org.apache.commons.logging.Log; |
| import org.apache.commons.logging.LogFactory; |
| import org.opensaml.*; |
| import org.opensaml.Configuration; |
| import org.opensaml.saml1.core.NameIdentifier; |
| import org.opensaml.xml.*; |
| import org.opensaml.xml.schema.impl.XSStringBuilder; |
| import org.opensaml.xml.schema.XSString; |
| import org.opensaml.xml.signature.*; |
| import org.opensaml.xml.io.*; |
| import org.opensaml.common.SAMLVersion; |
| import org.opensaml.common.SAMLObjectBuilder; |
| import org.opensaml.saml2.core.impl.AssertionBuilder; |
| import org.opensaml.saml2.core.impl.IssuerBuilder; |
| import org.opensaml.saml2.core.impl.NameIDBuilder; |
| import org.opensaml.saml2.core.*; |
| import org.joda.time.DateTime; |
| import org.w3c.dom.Document; |
| import org.w3c.dom.Element; |
| import org.w3c.dom.Text; |
| import org.w3c.dom.Node; |
| import org.w3c.dom.ls.DOMImplementationLS; |
| import org.w3c.dom.ls.LSOutput; |
| import org.w3c.dom.ls.LSSerializer; |
| import org.w3c.dom.bootstrap.DOMImplementationRegistry; |
| |
| import javax.xml.namespace.QName; |
| import javax.xml.parsers.DocumentBuilderFactory; |
| import javax.xml.parsers.DocumentBuilder; |
| import java.util.Date; |
| import java.util.List; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.security.cert.X509Certificate; |
| import java.security.cert.CertificateEncodingException; |
| import java.security.PrivateKey; |
| import java.text.DateFormat; |
| import java.io.InputStream; |
| import java.io.ByteArrayInputStream; |
| import java.io.ByteArrayOutputStream; |
| |
| public class SAML2TokenIssuer implements TokenIssuer { |
| |
| private Assertion SAMLAssertion; |
| |
| private String configParamName; |
| |
| private OMElement configElement; |
| |
| private String configFile; |
| |
| protected List<Signature> signatureList = new ArrayList<Signature>(); |
| |
| private boolean isSymmetricKeyBasedHoK = false; |
| |
| private static Log log = LogFactory.getLog(SAML2TokenIssuer.class); |
| |
| static { |
| try { |
| // Set the "javax.xml.parsers.DocumentBuilderFactory" system property |
| // to the endorsed JAXP impl. |
| System.setProperty("javax.xml.parsers.DocumentBuilderFactory", |
| "org.apache.xerces.jaxp.DocumentBuilderFactoryImpl"); |
| DefaultBootstrap.bootstrap(); |
| } catch (ConfigurationException e) { |
| log.error("SAML2TokenIssuerBootstrapError", e); |
| throw new RuntimeException(e); |
| } finally { |
| // Unset the DOM impl to default |
| DocumentBuilderFactoryImpl.setDOOMRequired(false); |
| } |
| } |
| |
| public SOAPEnvelope issue(RahasData data) throws TrustException { |
| MessageContext inMsgCtx = data.getInMessageContext(); |
| |
| try { |
| SAMLTokenIssuerConfig config = null; |
| if (this.configElement != null) { |
| config = new SAMLTokenIssuerConfig(configElement |
| .getFirstChildWithName(SAMLTokenIssuerConfig.SAML_ISSUER_CONFIG)); |
| } |
| |
| // Look for the file |
| if (config == null && this.configFile != null) { |
| config = new SAMLTokenIssuerConfig(this.configFile); |
| } |
| |
| // Look for the param |
| if (config == null && this.configParamName != null) { |
| Parameter param = inMsgCtx.getParameter(this.configParamName); |
| if (param != null && param.getParameterElement() != null) { |
| config = new SAMLTokenIssuerConfig(param.getParameterElement() |
| .getFirstChildWithName(SAMLTokenIssuerConfig.SAML_ISSUER_CONFIG)); |
| } else { |
| throw new TrustException("expectedParameterMissing", |
| new String[]{this.configParamName}); |
| } |
| } |
| |
| if (config == null) { |
| throw new TrustException("configurationIsNull"); |
| } |
| |
| SOAPEnvelope env = TrustUtil.createSOAPEnvelope(inMsgCtx.getEnvelope().getNamespace() |
| .getNamespaceURI()); |
| |
| Crypto crypto; |
| if (config.cryptoElement != null) { // crypto props |
| // defined as |
| // elements |
| crypto = CryptoFactory.getInstance(TrustUtil.toProperties(config.cryptoElement), |
| inMsgCtx.getAxisService().getClassLoader()); |
| } else { // crypto props defined in a properties file |
| crypto = CryptoFactory.getInstance(config.cryptoPropertiesFile, inMsgCtx |
| .getAxisService().getClassLoader()); |
| } |
| |
| // Get the document |
| Document doc = ((Element) env).getOwnerDocument(); |
| |
| // Get the key size and create a new byte array of that size |
| int keySize = data.getKeysize(); |
| String keyType = data.getKeyType(); |
| |
| keySize = (keySize == -1) ? config.keySize : keySize; |
| |
| // Build the assertion |
| AssertionBuilder assertionBuilder = new AssertionBuilder(); |
| Assertion assertion = assertionBuilder.buildObject(); |
| assertion.setVersion(SAMLVersion.VERSION_20); |
| |
| // Set an UUID as the ID of an assertion |
| assertion.setID(UUIDGenerator.getUUID()); |
| |
| // Set the issuer |
| IssuerBuilder issuerBuilder = new IssuerBuilder(); |
| Issuer issuer = issuerBuilder.buildObject(); |
| issuer.setValue(config.issuerName); |
| assertion.setIssuer(issuer); |
| |
| // Set the issued time. |
| assertion.setIssueInstant(new DateTime()); |
| |
| // Validity period |
| DateTime creationDate = new DateTime(); |
| DateTime expirationDate = new DateTime(creationDate.getMillis() + config.ttl); |
| |
| // These variables are used to build the trust assertion |
| Date creationTime = creationDate.toDate(); |
| Date expirationTime = expirationDate.toDate(); |
| |
| // Create the subject |
| Subject subject = createSubject(config, doc, crypto, creationDate, expirationDate, data); |
| |
| // Set the subject |
| assertion.setSubject(subject); |
| |
| // If a SymmetricKey is used build an attr stmt, if a public key is build an authn stmt. |
| if (isSymmetricKeyBasedHoK) { |
| AttributeStatement attrStmt = createAttributeStatement(data, config); |
| assertion.getAttributeStatements().add(attrStmt); |
| } else { |
| AuthnStatement authStmt = createAuthnStatement(data); |
| assertion.getAuthnStatements().add(authStmt); |
| } |
| |
| // Create a SignKeyHolder to hold the crypto objects that are used to sign the assertion |
| SignKeyHolder signKeyHolder = createSignKeyHolder(config, crypto); |
| |
| // Sign the assertion |
| assertion = setSignature(assertion, signKeyHolder); |
| |
| OMElement rstrElem; |
| int wstVersion = data.getVersion(); |
| if (RahasConstants.VERSION_05_02 == wstVersion) { |
| rstrElem = TrustUtil.createRequestSecurityTokenResponseElement(wstVersion, env |
| .getBody()); |
| } else { |
| OMElement rstrcElem = TrustUtil |
| .createRequestSecurityTokenResponseCollectionElement(wstVersion, env |
| .getBody()); |
| rstrElem = TrustUtil.createRequestSecurityTokenResponseElement(wstVersion, |
| rstrcElem); |
| } |
| |
| TrustUtil.createTokenTypeElement(wstVersion, rstrElem).setText( |
| RahasConstants.TOK_TYPE_SAML_20); |
| |
| if (keyType.endsWith(RahasConstants.KEY_TYPE_SYMM_KEY)) { |
| TrustUtil.createKeySizeElement(wstVersion, rstrElem, keySize); |
| } |
| |
| if (config.addRequestedAttachedRef) { |
| TrustUtil.createRequestedAttachedRef(wstVersion, rstrElem, "#" + assertion.getID(), |
| RahasConstants.TOK_TYPE_SAML_20); |
| } |
| |
| if (config.addRequestedUnattachedRef) { |
| TrustUtil.createRequestedUnattachedRef(wstVersion, rstrElem, assertion.getID(), |
| RahasConstants.TOK_TYPE_SAML_20); |
| } |
| |
| if (data.getAppliesToAddress() != null) { |
| TrustUtil.createAppliesToElement(rstrElem, data.getAppliesToAddress(), data |
| .getAddressingNs()); |
| } |
| |
| // Use GMT time in milliseconds |
| DateFormat zulu = new XmlSchemaDateFormat(); |
| |
| // Add the Lifetime element |
| TrustUtil.createLifetimeElement(wstVersion, rstrElem, zulu.format(creationTime), zulu |
| .format(expirationTime)); |
| |
| // Create the RequestedSecurityToken element and add the SAML token |
| // to it |
| OMElement reqSecTokenElem = TrustUtil.createRequestedSecurityTokenElement(wstVersion, |
| rstrElem); |
| Token assertionToken; |
| |
| Node tempNode = assertion.getDOM(); |
| |
| // Serializing and re-generating the AXIOM element using the DOM Element created using |
| // xerces |
| Element element = assertion.getDOM(); |
| |
| ByteArrayOutputStream byteArrayOutputStrm = new ByteArrayOutputStream(); |
| |
| DOMImplementationRegistry registry = DOMImplementationRegistry.newInstance(); |
| |
| DOMImplementationLS impl = (DOMImplementationLS) registry.getDOMImplementation("LS"); |
| |
| LSSerializer writer = impl.createLSSerializer(); |
| LSOutput output = impl.createLSOutput(); |
| output.setByteStream(byteArrayOutputStrm); |
| writer.write(element, output); |
| String elementString = byteArrayOutputStrm.toString(); |
| |
| DocumentBuilderFactoryImpl.setDOOMRequired(true); |
| |
| DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); |
| documentBuilderFactory.setNamespaceAware(true); |
| DocumentBuilder docBuilder = documentBuilderFactory.newDocumentBuilder(); |
| Document document = docBuilder.parse(new ByteArrayInputStream(elementString.trim() |
| .getBytes())); |
| Element assertionElement = document.getDocumentElement(); |
| |
| reqSecTokenElem.addChild((OMNode) ((Element) rstrElem).getOwnerDocument().importNode( |
| tempNode, true)); |
| |
| // Store the token |
| assertionToken = new Token(assertion.getID(), (OMElement) assertionElement, |
| creationTime, expirationTime); |
| |
| // At this point we definitely have the secret |
| // Otherwise it should fail with an exception earlier |
| assertionToken.setSecret(data.getEphmeralKey()); |
| TrustUtil.getTokenStore(inMsgCtx).add(assertionToken); |
| |
| if (keyType.endsWith(RahasConstants.KEY_TYPE_SYMM_KEY) |
| && config.keyComputation != SAMLTokenIssuerConfig.KeyComputation.KEY_COMP_USE_REQ_ENT) { |
| |
| // Add the RequestedProofToken |
| TokenIssuerUtil.handleRequestedProofToken(data, wstVersion, config, rstrElem, |
| assertionToken, doc); |
| } |
| |
| return env; |
| |
| } catch (Exception e) { |
| e.printStackTrace(); |
| } finally { |
| // Unset the DOM impl to default |
| DocumentBuilderFactoryImpl.setDOOMRequired(false); |
| } |
| |
| return null; |
| } |
| |
| /** |
| * This method is used to create the subject of an assertion |
| * |
| * @param config |
| * @param doc |
| * @param crypto |
| * @param creationTime |
| * @param expirationTime |
| * @param data |
| * @return Subject |
| * @throws Exception |
| */ |
| private Subject createSubject(SAMLTokenIssuerConfig config, Document doc, Crypto crypto, |
| DateTime creationTime, DateTime expirationTime, RahasData data) throws Exception { |
| |
| XMLObjectBuilderFactory builderFactory = Configuration.getBuilderFactory(); |
| SAMLObjectBuilder<Subject> subjectBuilder = (SAMLObjectBuilder<Subject>) builderFactory |
| .getBuilder(Subject.DEFAULT_ELEMENT_NAME); |
| Subject subject = subjectBuilder.buildObject(); |
| Element keyInfoElem = null; |
| |
| // If it is a Symmetric Key |
| if (data.getKeyType().endsWith(RahasConstants.KEY_TYPE_SYMM_KEY)) { |
| |
| isSymmetricKeyBasedHoK = true; |
| Element encryptedKeyElem; |
| X509Certificate serviceCert = null; |
| try { |
| |
| // Get ApliesTo to figure out which service to issue the token |
| // for |
| serviceCert = config.getServiceCert(crypto, data.getAppliesToAddress()); |
| |
| // Create the encrypted key |
| WSSecEncryptedKey encrKeyBuilder = new WSSecEncryptedKey(); |
| |
| // Use thumbprint id |
| encrKeyBuilder.setKeyIdentifierType(WSConstants.THUMBPRINT_IDENTIFIER); |
| |
| // SEt the encryption cert |
| encrKeyBuilder.setUseThisCert(serviceCert); |
| |
| // set keysize |
| int keysize = data.getKeysize(); |
| keysize = (keysize != -1) ? keysize : config.keySize; |
| encrKeyBuilder.setKeySize(keysize); |
| |
| encrKeyBuilder.setEphemeralKey(TokenIssuerUtil.getSharedSecret(data, |
| config.keyComputation, keysize)); |
| |
| // Set key encryption algo |
| encrKeyBuilder.setKeyEncAlgo(EncryptionConstants.ALGO_ID_KEYTRANSPORT_RSA15); |
| |
| // Build |
| encrKeyBuilder.prepare(doc, crypto); |
| |
| // Extract the base64 encoded secret value |
| byte[] tempKey = new byte[keysize / 8]; |
| System.arraycopy(encrKeyBuilder.getEphemeralKey(), 0, tempKey, 0, keysize / 8); |
| |
| data.setEphmeralKey(tempKey); |
| |
| // Extract the Encryptedkey DOM element |
| encryptedKeyElem = encrKeyBuilder.getEncryptedKeyElement(); |
| } catch (WSSecurityException e) { |
| throw new TrustException("errorInBuildingTheEncryptedKeyForPrincipal", |
| new String[]{serviceCert.getSubjectDN().getName()}, e); |
| } |
| |
| keyInfoElem = doc.createElementNS(WSConstants.SIG_NS, "ds:KeyInfo"); |
| ((OMElement) encryptedKeyElem).declareNamespace(WSConstants.SIG_NS, |
| WSConstants.SIG_PREFIX); |
| ((OMElement) encryptedKeyElem).declareNamespace(WSConstants.ENC_NS, |
| WSConstants.ENC_PREFIX); |
| |
| keyInfoElem.appendChild(encryptedKeyElem); |
| |
| } |
| |
| // If it is a public Key |
| else { |
| try { |
| String subjectNameId = data.getPrincipal().getName(); |
| |
| // Create NameID and attach it to the subject |
| NameIDBuilder nb = new NameIDBuilder(); |
| NameID nameID = nb.buildObject(); |
| nameID.setValue(subjectNameId); |
| nameID.setFormat(NameIdentifier.EMAIL); |
| subject.setNameID(nameID); |
| |
| // Create the ds:KeyValue element with the ds:X509Data |
| X509Certificate clientCert = data.getClientCert(); |
| |
| if (clientCert == null) { |
| X509Certificate[] certs = crypto.getCertificates(data.getPrincipal().getName()); |
| clientCert = certs[0]; |
| } |
| |
| byte[] clientCertBytes = clientCert.getEncoded(); |
| |
| String base64Cert = Base64.encode(clientCertBytes); |
| |
| Text base64CertText = doc.createTextNode(base64Cert); |
| |
| // ----------------------------------------- |
| |
| Element x509CertElem = doc |
| .createElementNS(WSConstants.SIG_NS, "ds:X509Certificate"); |
| x509CertElem.appendChild(base64CertText); |
| Element x509DataElem = doc.createElementNS(WSConstants.SIG_NS, "ds:X509Data"); |
| x509DataElem.appendChild(x509CertElem); |
| |
| if (x509DataElem != null) { |
| keyInfoElem = doc.createElementNS(WSConstants.SIG_NS, "ds:KeyInfo"); |
| ((OMElement) x509DataElem).declareNamespace(WSConstants.SIG_NS, |
| WSConstants.SIG_PREFIX); |
| ((OMElement) x509DataElem).declareNamespace(WSConstants.ENC_NS, |
| WSConstants.ENC_PREFIX); |
| |
| keyInfoElem.appendChild(x509DataElem); |
| } |
| |
| } catch (Exception e) { |
| throw new TrustException("samlAssertionCreationError", e); |
| } |
| } |
| |
| // Unmarshall the keyInfo DOM element into an XMLObject |
| String keyInfoElementString = keyInfoElem.toString(); |
| DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); |
| documentBuilderFactory.setNamespaceAware(true); |
| DocumentBuilder docBuilder = documentBuilderFactory.newDocumentBuilder(); |
| Document document = docBuilder.parse(new ByteArrayInputStream(keyInfoElementString.trim() |
| .getBytes())); |
| Element element = document.getDocumentElement(); |
| |
| // Get appropriate unmarshaller |
| UnmarshallerFactory unmarshallerFactory = Configuration.getUnmarshallerFactory(); |
| Unmarshaller unmarshaller = unmarshallerFactory.getUnmarshaller(element); |
| |
| // Unmarshall using the document root element, an keyInfo element in this case |
| XMLObject keyInfoElement = null; |
| try { |
| keyInfoElement = unmarshaller.unmarshall(element); |
| } catch (UnmarshallingException e) { |
| throw new TrustException("Error unmarshalling KeyInfo Element", e); |
| } |
| |
| // Build the Subject Confirmation |
| SAMLObjectBuilder<SubjectConfirmation> subjectConfirmationBuilder = (SAMLObjectBuilder<SubjectConfirmation>) builderFactory |
| .getBuilder(SubjectConfirmation.DEFAULT_ELEMENT_NAME); |
| SubjectConfirmation subjectConfirmation = subjectConfirmationBuilder.buildObject(); |
| |
| // Set the subject Confirmation method |
| subjectConfirmation.setMethod("urn:oasis:names:tc:SAML:2.0:cm:holder-of-key"); |
| |
| SAMLObjectBuilder<KeyInfoConfirmationDataType> keyInfoSubjectConfirmationDataBuilder = (SAMLObjectBuilder<KeyInfoConfirmationDataType>) builderFactory |
| .getBuilder(KeyInfoConfirmationDataType.TYPE_NAME); |
| |
| // Build the subject confirmation data element |
| KeyInfoConfirmationDataType scData = keyInfoSubjectConfirmationDataBuilder |
| .buildObject(SubjectConfirmationData.DEFAULT_ELEMENT_NAME, |
| KeyInfoConfirmationDataType.TYPE_NAME); |
| |
| // Set the keyInfo element |
| scData.getKeyInfos().add(keyInfoElement); |
| |
| // Set the validity period |
| scData.setNotBefore(creationTime); |
| scData.setNotOnOrAfter(expirationTime); |
| |
| // Set the subject confirmation data |
| subjectConfirmation.setSubjectConfirmationData(scData); |
| |
| // set the subject confirmation |
| subject.getSubjectConfirmations().add(subjectConfirmation); |
| |
| if (log.isDebugEnabled()) { |
| log.debug("SAML2.0 subject is constructed successfully."); |
| } |
| return subject; |
| } |
| |
| /** |
| * This method is used to sign the assertion |
| * |
| * @param assertion |
| * @param cred |
| * @return Assertion |
| * @throws Exception |
| */ |
| public Assertion setSignature(Assertion assertion, SignKeyHolder cred) throws Exception { |
| |
| // Build the signature object and set the credentials. |
| Signature signature = (Signature) buildXMLObject(Signature.DEFAULT_ELEMENT_NAME); |
| signature.setSigningCredential(cred); |
| signature.setSignatureAlgorithm(cred.getSignatureAlgorithm()); |
| signature.setCanonicalizationAlgorithm(Canonicalizer.ALGO_ID_C14N_EXCL_OMIT_COMMENTS); |
| |
| // Build the KeyInfo element and set the certificate |
| try { |
| KeyInfo keyInfo = (KeyInfo) buildXMLObject(KeyInfo.DEFAULT_ELEMENT_NAME); |
| X509Data data = (X509Data) buildXMLObject(X509Data.DEFAULT_ELEMENT_NAME); |
| org.opensaml.xml.signature.X509Certificate cert = (org.opensaml.xml.signature.X509Certificate) buildXMLObject(org.opensaml.xml.signature.X509Certificate.DEFAULT_ELEMENT_NAME); |
| String value = org.apache.xml.security.utils.Base64.encode(cred.getEntityCertificate() |
| .getEncoded()); |
| cert.setValue(value); |
| data.getX509Certificates().add(cert); |
| keyInfo.getX509Datas().add(data); |
| signature.setKeyInfo(keyInfo); |
| |
| assertion.setSignature(signature); |
| signatureList.add(signature); |
| |
| // Marshall and Sign |
| MarshallerFactory marshallerFactory = org.opensaml.xml.Configuration |
| .getMarshallerFactory(); |
| Marshaller marshaller = marshallerFactory.getMarshaller(assertion); |
| marshaller.marshall(assertion); |
| org.apache.xml.security.Init.init(); |
| Signer.signObjects(signatureList); |
| } catch (CertificateEncodingException e) { |
| throw new TrustException("Error in setting the signature", e); |
| } catch (SignatureException e) { |
| throw new TrustException("errorMarshellingOrSigning", e); |
| } catch (MarshallingException e) { |
| throw new TrustException("errorMarshellingOrSigning", e); |
| } |
| |
| if (log.isDebugEnabled()) { |
| log.debug("SAML2.0 assertion is marshalled and signed.."); |
| } |
| |
| return assertion; |
| } |
| |
| /** |
| * This method is used to build the assertion elements |
| * |
| * @param objectQName |
| * @return |
| * @throws Exception |
| */ |
| protected static XMLObject buildXMLObject(QName objectQName) throws Exception { |
| XMLObjectBuilder builder = org.opensaml.xml.Configuration.getBuilderFactory().getBuilder( |
| objectQName); |
| if (builder == null) { |
| throw new TrustException("Unable to retrieve builder for object QName " + objectQName); |
| } |
| return builder.buildObject(objectQName.getNamespaceURI(), objectQName.getLocalPart(), |
| objectQName.getPrefix()); |
| } |
| |
| /** |
| * This method is used to create SignKeyHolder instances that contains the credentials required |
| * for signing the assertion |
| * |
| * @param config |
| * @param crypto |
| * @return |
| * @throws TrustException |
| */ |
| private SignKeyHolder createSignKeyHolder(SAMLTokenIssuerConfig config, Crypto crypto) |
| throws TrustException { |
| |
| SignKeyHolder signKeyHolder = new SignKeyHolder(); |
| |
| try { |
| X509Certificate[] issuerCerts = crypto.getCertificates(config.issuerKeyAlias); |
| |
| String sigAlgo = XMLSignature.ALGO_ID_SIGNATURE_RSA; |
| String pubKeyAlgo = issuerCerts[0].getPublicKey().getAlgorithm(); |
| if (pubKeyAlgo.equalsIgnoreCase("DSA")) { |
| sigAlgo = XMLSignature.ALGO_ID_SIGNATURE_DSA; |
| } |
| java.security.Key issuerPK = crypto.getPrivateKey(config.issuerKeyAlias, |
| config.issuerKeyPassword); |
| |
| signKeyHolder.setIssuerCerts(issuerCerts); |
| signKeyHolder.setIssuerPK((PrivateKey) issuerPK); |
| signKeyHolder.setSignatureAlgorithm(sigAlgo); |
| |
| } catch (Exception e) { |
| throw new TrustException("Error creating issuer signature"); |
| } |
| |
| if (log.isDebugEnabled()) { |
| log.debug("SignKeyHolder object is created with the credentials.."); |
| } |
| |
| return signKeyHolder; |
| } |
| |
| /** |
| * Creates the Attribute Statement |
| * |
| * @param data |
| * @param config |
| * @return |
| * @throws SAMLException |
| * @throws TrustException |
| */ |
| private AttributeStatement createAttributeStatement(RahasData data, SAMLTokenIssuerConfig config) |
| throws SAMLException, TrustException { |
| |
| XMLObjectBuilderFactory builderFactory = Configuration.getBuilderFactory(); |
| SAMLObjectBuilder<AttributeStatement> attrStmtBuilder = (SAMLObjectBuilder<AttributeStatement>) builderFactory |
| .getBuilder(AttributeStatement.DEFAULT_ELEMENT_NAME); |
| |
| AttributeStatement attrstmt = attrStmtBuilder.buildObject(); |
| |
| Attribute[] attributes = null; |
| |
| // Call the attribute callback handlers to get any attributes if exists |
| if (config.getCallbackHander() != null) { |
| SAMLAttributeCallback cb = new SAMLAttributeCallback(data); |
| SAMLCallbackHandler handler = config.getCallbackHander(); |
| handler.handle(cb); |
| attributes = cb.getSAML2Attributes(); |
| } else if (config.getCallbackHandlerName() != null |
| && config.getCallbackHandlerName().trim().length() > 0) { |
| SAMLAttributeCallback cb = new SAMLAttributeCallback(data); |
| SAMLCallbackHandler handler = null; |
| MessageContext msgContext = data.getInMessageContext(); |
| ClassLoader classLoader = msgContext.getAxisService().getClassLoader(); |
| Class cbClass = null; |
| try { |
| cbClass = Loader.loadClass(classLoader, config.getCallbackHandlerName()); |
| } catch (ClassNotFoundException e) { |
| throw new TrustException("cannotLoadPWCBClass", new String[]{config |
| .getCallbackHandlerName()}, e); |
| } |
| try { |
| handler = (SAMLCallbackHandler) cbClass.newInstance(); |
| } catch (java.lang.Exception e) { |
| throw new TrustException("cannotCreatePWCBInstance", new String[]{config |
| .getCallbackHandlerName()}, e); |
| } |
| handler.handle(cb); |
| attributes = cb.getSAML2Attributes(); |
| // else add the attribute with a default value |
| } else { |
| SAMLObjectBuilder<Attribute> attrBuilder = (SAMLObjectBuilder<Attribute>) builderFactory |
| .getBuilder(Attribute.DEFAULT_ELEMENT_NAME); |
| Attribute attribute = attrBuilder.buildObject(); |
| attribute.setName("Name"); |
| attribute.setNameFormat("urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified"); |
| |
| XSStringBuilder attributeValueBuilder = (XSStringBuilder) builderFactory |
| .getBuilder(XSString.TYPE_NAME); |
| |
| XSString stringValue = attributeValueBuilder.buildObject( |
| AttributeValue.DEFAULT_ELEMENT_NAME, XSString.TYPE_NAME); |
| stringValue.setValue("Colombo/Rahas"); |
| attribute.getAttributeValues().add(stringValue); |
| attributes = new Attribute[1]; |
| attributes[0] = attribute; |
| } |
| // add attributes to the attribute statement |
| attrstmt.getAttributes().addAll(Arrays.asList(attributes)); |
| |
| if (log.isDebugEnabled()) { |
| log.debug("SAML2.0 attribute statement is constructed successfully."); |
| } |
| |
| return attrstmt; |
| } |
| |
| /** |
| * build the authentication statement |
| * |
| * @param data |
| * @return |
| */ |
| private AuthnStatement createAuthnStatement(RahasData data) { |
| XMLObjectBuilderFactory builderFactory = Configuration.getBuilderFactory(); |
| MessageContext inMsgCtx = data.getInMessageContext(); |
| |
| SAMLObjectBuilder<AuthnStatement> authStmtBuilder = (SAMLObjectBuilder<AuthnStatement>) builderFactory |
| .getBuilder(AuthnStatement.DEFAULT_ELEMENT_NAME); |
| |
| // build the auth stmt |
| AuthnStatement authStmt = authStmtBuilder.buildObject(); |
| |
| // set the authn instance |
| authStmt.setAuthnInstant(new DateTime()); |
| |
| SAMLObjectBuilder<AuthnContext> authCtxBuilder = (SAMLObjectBuilder<AuthnContext>) builderFactory |
| .getBuilder(AuthnContext.DEFAULT_ELEMENT_NAME); |
| AuthnContext authContext = authCtxBuilder.buildObject(); |
| |
| SAMLObjectBuilder<AuthnContextClassRef> authCtxClassRefBuilder = (SAMLObjectBuilder<AuthnContextClassRef>) builderFactory |
| .getBuilder(AuthnContextClassRef.DEFAULT_ELEMENT_NAME); |
| AuthnContextClassRef authCtxClassRef = authCtxClassRefBuilder.buildObject(); |
| |
| // if username/password based authn |
| if (inMsgCtx.getProperty(RahasConstants.USERNAME) != null) { |
| authCtxClassRef.setAuthnContextClassRef(AuthnContext.PASSWORD_AUTHN_CTX); |
| } |
| // if X.509 cert based authn |
| else if (inMsgCtx.getProperty(RahasConstants.X509_CERT) != null) { |
| authCtxClassRef.setAuthnContextClassRef(AuthnContext.X509_AUTHN_CTX); |
| } |
| |
| authContext.setAuthnContextClassRef(authCtxClassRef); |
| authStmt.setAuthnContext(authContext); |
| |
| if (log.isDebugEnabled()) { |
| log.debug("SAML2.0 authentication statement is constructed successfully."); |
| } |
| |
| return authStmt; |
| } |
| |
| public String getResponseAction(RahasData data) throws TrustException { |
| return null; |
| } |
| |
| public void setConfigurationFile(String configFile) { |
| this.configFile = configFile; |
| } |
| |
| public void setConfigurationElement(OMElement configElement) { |
| this.configElement = configElement; |
| } |
| |
| public void setConfigurationParamName(String configParamName) { |
| this.configParamName = configParamName; |
| } |
| |
| } |