| <?xml version="1.0" encoding="UTF-8"?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml" lang="en"><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/><link rel="stylesheet" href="../.resources/report.css" type="text/css"/><link rel="shortcut icon" href="../.resources/report.gif" type="image/gif"/><title>SAML2TokenIssuer.java</title><link rel="stylesheet" href="../.resources/prettify.css" type="text/css"/><script type="text/javascript" src="../.resources/prettify.js"></script></head><body onload="window['PR_TAB_WIDTH']=4;prettyPrint()"><div class="breadcrumb" id="breadcrumb"><span class="right"><a href="../.sessions.html" class="el_session">Sessions</a></span><a href="../index.html" class="el_report">Coverage Report</a> > <a href="index.html" class="el_package">org.apache.rahas.impl</a> > <span class="el_source">SAML2TokenIssuer.java</span></div><h1>SAML2TokenIssuer.java</h1><pre class="source lang-java linenums">/* |
| * 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.axiom.om.OMElement; |
| import org.apache.axiom.om.OMNode; |
| import org.apache.axiom.om.impl.dom.jaxp.DocumentBuilderFactoryImpl; |
| import org.apache.axiom.om.util.UUIDGenerator; |
| import org.apache.axiom.soap.SOAPEnvelope; |
| import org.apache.axis2.context.MessageContext; |
| import org.apache.axis2.description.Parameter; |
| import org.apache.commons.logging.Log; |
| import org.apache.commons.logging.LogFactory; |
| import org.apache.rahas.*; |
| import org.apache.rahas.impl.util.CommonUtil; |
| import org.apache.rahas.impl.util.SAMLAttributeCallback; |
| import org.apache.rahas.impl.util.SAMLCallbackHandler; |
| import org.apache.rahas.impl.util.SignKeyHolder; |
| import org.apache.ws.security.WSConstants; |
| import org.apache.ws.security.WSSecurityException; |
| 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.util.Base64; |
| import org.apache.ws.security.util.Loader; |
| import org.apache.ws.security.util.XmlSchemaDateFormat; |
| import org.apache.xml.security.c14n.Canonicalizer; |
| import org.apache.xml.security.signature.XMLSignature; |
| import org.apache.xml.security.utils.EncryptionConstants; |
| import org.joda.time.DateTime; |
| import org.opensaml.Configuration; |
| import org.opensaml.DefaultBootstrap; |
| import org.opensaml.common.SAMLException; |
| import org.opensaml.common.SAMLObjectBuilder; |
| import org.opensaml.common.SAMLVersion; |
| import org.opensaml.saml1.core.NameIdentifier; |
| import org.opensaml.saml2.core.*; |
| import org.opensaml.saml2.core.impl.AssertionBuilder; |
| import org.opensaml.saml2.core.impl.ConditionsBuilder; |
| import org.opensaml.saml2.core.impl.IssuerBuilder; |
| import org.opensaml.saml2.core.impl.NameIDBuilder; |
| import org.opensaml.xml.ConfigurationException; |
| import org.opensaml.xml.XMLObject; |
| import org.opensaml.xml.XMLObjectBuilder; |
| import org.opensaml.xml.XMLObjectBuilderFactory; |
| import org.opensaml.xml.io.*; |
| import org.opensaml.xml.schema.XSString; |
| import org.opensaml.xml.schema.impl.XSStringBuilder; |
| import org.opensaml.xml.signature.*; |
| import org.w3c.dom.Document; |
| import org.w3c.dom.Element; |
| import org.w3c.dom.Node; |
| import org.w3c.dom.Text; |
| import org.w3c.dom.bootstrap.DOMImplementationRegistry; |
| import org.w3c.dom.ls.DOMImplementationLS; |
| import org.w3c.dom.ls.LSOutput; |
| import org.w3c.dom.ls.LSSerializer; |
| |
| import javax.xml.namespace.QName; |
| import javax.xml.parsers.DocumentBuilder; |
| import javax.xml.parsers.DocumentBuilderFactory; |
| import java.io.ByteArrayInputStream; |
| import java.io.ByteArrayOutputStream; |
| import java.security.PrivateKey; |
| import java.security.cert.CertificateEncodingException; |
| import java.security.cert.X509Certificate; |
| import java.text.DateFormat; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Date; |
| import java.util.List; |
| |
| <span class="fc" id="L87">public class SAML2TokenIssuer implements TokenIssuer {</span> |
| |
| private String configParamName; |
| |
| private OMElement configElement; |
| |
| private String configFile; |
| |
| <span class="fc" id="L95"> protected List<Signature> signatureList = new ArrayList<Signature>();</span> |
| |
| <span class="fc" id="L97"> private boolean isSymmetricKeyBasedHoK = false;</span> |
| |
| <span class="fc" id="L99"> private static Log log = LogFactory.getLog(SAML2TokenIssuer.class);</span> |
| |
| static { |
| try { |
| // Set the "javax.xml.parsers.DocumentBuilderFactory" system property |
| // to the endorsed JAXP impl. |
| <span class="fc" id="L105"> System.setProperty("javax.xml.parsers.DocumentBuilderFactory",</span> |
| "org.apache.xerces.jaxp.DocumentBuilderFactoryImpl"); |
| <span class="fc" id="L107"> DefaultBootstrap.bootstrap();</span> |
| <span class="nc" id="L108"> } catch (ConfigurationException e) {</span> |
| <span class="nc" id="L109"> log.error("SAML2TokenIssuerBootstrapError", e);</span> |
| <span class="nc" id="L110"> throw new RuntimeException(e);</span> |
| } finally { |
| // Unset the DOM impl to default |
| <span class="pc" id="L113"> DocumentBuilderFactoryImpl.setDOOMRequired(false);</span> |
| <span class="fc" id="L114"> }</span> |
| <span class="fc" id="L115"> }</span> |
| |
| public SOAPEnvelope issue(RahasData data) throws TrustException { |
| <span class="fc" id="L118"> MessageContext inMsgCtx = data.getInMessageContext();</span> |
| |
| try { |
| <span class="fc" id="L121"> SAMLTokenIssuerConfig config = null;</span> |
| <span class="pc bpc" id="L122" title="1 of 2 branches missed."> if (this.configElement != null) {</span> |
| <span class="nc" id="L123"> config = new SAMLTokenIssuerConfig(configElement</span> |
| .getFirstChildWithName(SAMLTokenIssuerConfig.SAML_ISSUER_CONFIG)); |
| } |
| |
| // Look for the file |
| <span class="pc bpc" id="L128" title="2 of 4 branches missed."> if (config == null && this.configFile != null) {</span> |
| <span class="nc" id="L129"> config = new SAMLTokenIssuerConfig(this.configFile);</span> |
| //config = new SAMLTokenIssuerConfig("/home/thilina/Desktop/saml-issuer-config.xml"); |
| } |
| |
| // Look for the param |
| <span class="pc bpc" id="L134" title="2 of 4 branches missed."> if (config == null && this.configParamName != null) {</span> |
| <span class="fc" id="L135"> Parameter param = inMsgCtx.getParameter(this.configParamName);</span> |
| <span class="pc bpc" id="L136" title="2 of 4 branches missed."> if (param != null && param.getParameterElement() != null) {</span> |
| <span class="fc" id="L137"> config = new SAMLTokenIssuerConfig(param</span> |
| .getParameterElement().getFirstChildWithName( |
| SAMLTokenIssuerConfig.SAML_ISSUER_CONFIG)); |
| } else { |
| <span class="nc" id="L141"> throw new TrustException("expectedParameterMissing",</span> |
| new String[]{this.configParamName}); |
| } |
| } |
| |
| <span class="pc bpc" id="L146" title="1 of 2 branches missed."> if (config == null) {</span> |
| <span class="nc" id="L147"> throw new TrustException("configurationIsNull");</span> |
| } |
| |
| <span class="fc" id="L150"> SOAPEnvelope env = TrustUtil.createSOAPEnvelope(inMsgCtx</span> |
| .getEnvelope().getNamespace().getNamespaceURI()); |
| |
| Crypto crypto; |
| <span class="pc bpc" id="L154" title="1 of 2 branches missed."> if (config.cryptoElement != null) { // crypto props</span> |
| // defined as |
| // elements |
| <span class="fc" id="L157"> crypto = CryptoFactory.getInstance(TrustUtil</span> |
| .toProperties(config.cryptoElement), inMsgCtx |
| .getAxisService().getClassLoader()); |
| } else { // crypto props defined in a properties file |
| <span class="nc" id="L161"> crypto = CryptoFactory.getInstance(config.cryptoPropertiesFile,</span> |
| inMsgCtx.getAxisService().getClassLoader()); |
| } |
| |
| |
| // Get the document |
| <span class="fc" id="L167"> Document doc = ((Element) env).getOwnerDocument();</span> |
| |
| // Get the key size and create a new byte array of that size |
| <span class="fc" id="L170"> int keySize = data.getKeysize();</span> |
| <span class="fc" id="L171"> String keyType = data.getKeyType();</span> |
| |
| <span class="pc bpc" id="L173" title="1 of 2 branches missed."> keySize = (keySize == -1) ? config.keySize : keySize;</span> |
| |
| //Build the assertion |
| <span class="fc" id="L176"> AssertionBuilder assertionBuilder = new AssertionBuilder();</span> |
| <span class="fc" id="L177"> Assertion assertion = assertionBuilder.buildObject();</span> |
| <span class="fc" id="L178"> assertion.setVersion(SAMLVersion.VERSION_20);</span> |
| |
| // Set an UUID as the ID of an assertion |
| <span class="fc" id="L181"> assertion.setID(UUIDGenerator.getUUID());</span> |
| |
| //Set the issuer |
| <span class="fc" id="L184"> IssuerBuilder issuerBuilder = new IssuerBuilder();</span> |
| <span class="fc" id="L185"> Issuer issuer = issuerBuilder.buildObject();</span> |
| <span class="fc" id="L186"> issuer.setValue(config.issuerName);</span> |
| <span class="fc" id="L187"> assertion.setIssuer(issuer);</span> |
| |
| // Set the issued time. |
| <span class="fc" id="L190"> assertion.setIssueInstant(new DateTime());</span> |
| |
| // Validity period |
| <span class="fc" id="L193"> DateTime creationDate = new DateTime();</span> |
| <span class="fc" id="L194"> DateTime expirationDate = new DateTime(creationDate.getMillis() + config.ttl);</span> |
| |
| // These variables are used to build the trust assertion |
| <span class="fc" id="L197"> Date creationTime = creationDate.toDate();</span> |
| <span class="fc" id="L198"> Date expirationTime = expirationDate.toDate();</span> |
| |
| <span class="fc" id="L200"> Conditions conditions = new ConditionsBuilder().buildObject();</span> |
| <span class="fc" id="L201"> conditions.setNotBefore(creationDate);</span> |
| <span class="fc" id="L202"> conditions.setNotOnOrAfter(expirationDate);</span> |
| <span class="fc" id="L203"> assertion.setConditions(conditions);</span> |
| |
| // Create the subject |
| Subject subject; |
| |
| <span class="fc bfc" id="L208" title="All 2 branches covered."> if (!data.getKeyType().endsWith(RahasConstants.KEY_TYPE_BEARER)) {</span> |
| <span class="fc" id="L209"> subject = createSubjectWithHolderOfKeySC(config, doc, crypto, creationDate, expirationDate, data);</span> |
| } |
| else{ |
| <span class="fc" id="L212"> subject = createSubjectWithBearerSC(data);</span> |
| } |
| |
| // Set the subject |
| <span class="fc" id="L216"> assertion.setSubject(subject);</span> |
| |
| // If a SymmetricKey is used build an attr stmt, if a public key is build an authn stmt. |
| <span class="fc bfc" id="L219" title="All 2 branches covered."> if (isSymmetricKeyBasedHoK) {</span> |
| <span class="fc" id="L220"> AttributeStatement attrStmt = createAttributeStatement(data, config);</span> |
| <span class="fc" id="L221"> assertion.getAttributeStatements().add(attrStmt);</span> |
| <span class="fc" id="L222"> } else {</span> |
| <span class="fc" id="L223"> AuthnStatement authStmt = createAuthnStatement(data);</span> |
| <span class="fc" id="L224"> assertion.getAuthnStatements().add(authStmt);</span> |
| <span class="pc bpc" id="L225" title="3 of 4 branches missed."> if (data.getClaimDialect() != null && data.getClaimElem() != null) {</span> |
| <span class="nc" id="L226"> assertion.getAttributeStatements().add(createAttributeStatement(data, config));</span> |
| } |
| } |
| |
| // Create a SignKeyHolder to hold the crypto objects that are used to sign the assertion |
| <span class="fc" id="L231"> SignKeyHolder signKeyHolder = createSignKeyHolder(config, crypto);</span> |
| |
| // Sign the assertion |
| <span class="fc" id="L234"> assertion = setSignature(assertion, signKeyHolder);</span> |
| |
| |
| OMElement rstrElem; |
| <span class="fc" id="L238"> int wstVersion = data.getVersion();</span> |
| <span class="pc bpc" id="L239" title="1 of 2 branches missed."> if (RahasConstants.VERSION_05_02 == wstVersion) {</span> |
| <span class="fc" id="L240"> rstrElem = TrustUtil.createRequestSecurityTokenResponseElement(</span> |
| wstVersion, env.getBody()); |
| } else { |
| <span class="nc" id="L243"> OMElement rstrcElem = TrustUtil</span> |
| .createRequestSecurityTokenResponseCollectionElement( |
| wstVersion, env.getBody()); |
| <span class="nc" id="L246"> rstrElem = TrustUtil.createRequestSecurityTokenResponseElement(</span> |
| wstVersion, rstrcElem); |
| } |
| |
| <span class="fc" id="L250"> TrustUtil.createTokenTypeElement(wstVersion, rstrElem).setText(</span> |
| RahasConstants.TOK_TYPE_SAML_20); |
| |
| <span class="fc bfc" id="L253" title="All 2 branches covered."> if (keyType.endsWith(RahasConstants.KEY_TYPE_SYMM_KEY)) {</span> |
| <span class="fc" id="L254"> TrustUtil.createKeySizeElement(wstVersion, rstrElem, keySize);</span> |
| } |
| |
| <span class="pc bpc" id="L257" title="1 of 2 branches missed."> if (config.addRequestedAttachedRef) {</span> |
| <span class="fc" id="L258"> TrustUtil.createRequestedAttachedRef(wstVersion, rstrElem, "#"</span> |
| + assertion.getID(), RahasConstants.TOK_TYPE_SAML_20); |
| } |
| |
| <span class="pc bpc" id="L262" title="1 of 2 branches missed."> if (config.addRequestedUnattachedRef) {</span> |
| <span class="fc" id="L263"> TrustUtil.createRequestedUnattachedRef(wstVersion, rstrElem,</span> |
| assertion.getID(), RahasConstants.TOK_TYPE_SAML_20); |
| } |
| |
| <span class="fc bfc" id="L267" title="All 2 branches covered."> if (data.getAppliesToAddress() != null) {</span> |
| <span class="fc" id="L268"> TrustUtil.createAppliesToElement(rstrElem, data</span> |
| .getAppliesToAddress(), data.getAddressingNs()); |
| } |
| |
| // Use GMT time in milliseconds |
| <span class="fc" id="L273"> DateFormat zulu = new XmlSchemaDateFormat();</span> |
| |
| // Add the Lifetime element |
| <span class="fc" id="L276"> TrustUtil.createLifetimeElement(wstVersion, rstrElem, zulu</span> |
| .format(creationTime), zulu.format(expirationTime)); |
| |
| // Create the RequestedSecurityToken element and add the SAML token |
| // to it |
| <span class="fc" id="L281"> OMElement reqSecTokenElem = TrustUtil</span> |
| .createRequestedSecurityTokenElement(wstVersion, rstrElem); |
| Token assertionToken; |
| |
| <span class="fc" id="L285"> Node tempNode = assertion.getDOM();</span> |
| |
| //Serializing and re-generating the AXIOM element using the DOM Element created using xerces |
| <span class="fc" id="L288"> Element element = assertion.getDOM();</span> |
| |
| <span class="fc" id="L290"> ByteArrayOutputStream byteArrayOutputStrm = new ByteArrayOutputStream();</span> |
| |
| <span class="fc" id="L292"> DOMImplementationRegistry registry = DOMImplementationRegistry.newInstance();</span> |
| |
| <span class="fc" id="L294"> DOMImplementationLS impl =</span> |
| (DOMImplementationLS) registry.getDOMImplementation("LS"); |
| |
| <span class="fc" id="L297"> LSSerializer writer = impl.createLSSerializer();</span> |
| <span class="fc" id="L298"> LSOutput output = impl.createLSOutput();</span> |
| <span class="fc" id="L299"> output.setByteStream(byteArrayOutputStrm);</span> |
| <span class="fc" id="L300"> writer.write(element, output);</span> |
| <span class="fc" id="L301"> String elementString = byteArrayOutputStrm.toString();</span> |
| |
| <span class="fc" id="L303"> DocumentBuilderFactoryImpl.setDOOMRequired(true);</span> |
| |
| <span class="fc" id="L305"> DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();</span> |
| <span class="fc" id="L306"> documentBuilderFactory.setNamespaceAware(true);</span> |
| <span class="fc" id="L307"> DocumentBuilder docBuilder = documentBuilderFactory.newDocumentBuilder();</span> |
| <span class="fc" id="L308"> Document document = docBuilder.parse(new ByteArrayInputStream(elementString.trim().getBytes()));</span> |
| <span class="fc" id="L309"> Element assertionElement = document.getDocumentElement();</span> |
| |
| <span class="fc" id="L311"> reqSecTokenElem.addChild((OMNode) ((Element) rstrElem)</span> |
| .getOwnerDocument().importNode(tempNode, true)); |
| |
| // Store the token |
| <span class="fc" id="L315"> assertionToken = new Token(assertion.getID(),</span> |
| (OMElement) assertionElement, creationTime, |
| expirationTime); |
| |
| // At this point we definitely have the secret |
| // Otherwise it should fail with an exception earlier |
| <span class="fc" id="L321"> assertionToken.setSecret(data.getEphmeralKey());</span> |
| <span class="fc" id="L322"> TrustUtil.getTokenStore(inMsgCtx).add(assertionToken);</span> |
| |
| <span class="pc bpc" id="L324" title="1 of 4 branches missed."> if (keyType.endsWith(RahasConstants.KEY_TYPE_SYMM_KEY)</span> |
| && config.keyComputation != SAMLTokenIssuerConfig.KeyComputation.KEY_COMP_USE_REQ_ENT) { |
| |
| // Add the RequestedProofToken |
| <span class="fc" id="L328"> TokenIssuerUtil.handleRequestedProofToken(data, wstVersion,</span> |
| config, rstrElem, assertionToken, doc); |
| } |
| |
| <span class="fc" id="L332"> return env;</span> |
| |
| <span class="nc" id="L334"> } catch (Exception e) {</span> |
| <span class="nc" id="L335"> e.printStackTrace();</span> |
| } |
| finally { |
| // Unset the DOM impl to default |
| <span class="pc" id="L339"> DocumentBuilderFactoryImpl.setDOOMRequired(false);</span> |
| <span class="nc" id="L340"> }</span> |
| |
| |
| <span class="nc" id="L343"> return null;</span> |
| } |
| |
| /** |
| * 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 |
| */ |
| Subject createSubjectWithHolderOfKeySC(SAMLTokenIssuerConfig config, |
| Document doc, Crypto crypto, |
| DateTime creationTime, |
| DateTime expirationTime, RahasData data) throws Exception { |
| |
| |
| // TODO modify these to use proper SAML apis |
| |
| <span class="fc" id="L365"> XMLObjectBuilderFactory builderFactory = Configuration.getBuilderFactory();</span> |
| <span class="fc" id="L366"> SAMLObjectBuilder<Subject> subjectBuilder =</span> |
| (SAMLObjectBuilder<Subject>) builderFactory.getBuilder(Subject.DEFAULT_ELEMENT_NAME); |
| <span class="fc" id="L368"> Subject subject = subjectBuilder.buildObject();</span> |
| <span class="fc" id="L369"> Element keyInfoElem = null;</span> |
| |
| // If it is a Symmetric Key |
| <span class="fc bfc" id="L372" title="All 2 branches covered."> if (data.getKeyType().endsWith(RahasConstants.KEY_TYPE_SYMM_KEY)) {</span> |
| |
| <span class="fc" id="L374"> isSymmetricKeyBasedHoK = true;</span> |
| Element encryptedKeyElem; |
| <span class="fc" id="L376"> X509Certificate serviceCert = null;</span> |
| try { |
| |
| // Get ApliesTo to figure out which service to issue the token |
| // for |
| <span class="fc" id="L381"> serviceCert = config.getServiceCert(crypto, data.getAppliesToAddress());</span> |
| |
| // Create the encrypted key |
| <span class="fc" id="L384"> WSSecEncryptedKey encrKeyBuilder = new WSSecEncryptedKey();</span> |
| |
| // Use thumbprint id |
| <span class="fc" id="L387"> encrKeyBuilder</span> |
| .setKeyIdentifierType(WSConstants.THUMBPRINT_IDENTIFIER); |
| |
| // SEt the encryption cert |
| <span class="fc" id="L391"> encrKeyBuilder.setUseThisCert(serviceCert);</span> |
| |
| // set keysize |
| <span class="fc" id="L394"> int keysize = data.getKeysize();</span> |
| <span class="pc bpc" id="L395" title="1 of 2 branches missed."> keysize = (keysize != -1) ? keysize : config.keySize;</span> |
| |
| // TODO setting keysize is removed with wss4j 1.6 migration - do we actually need this ? |
| |
| <span class="fc" id="L399"> encrKeyBuilder.setEphemeralKey(TokenIssuerUtil.getSharedSecret(</span> |
| data, config.keyComputation, keysize)); |
| |
| |
| // Set key encryption algo |
| <span class="fc" id="L404"> encrKeyBuilder</span> |
| .setKeyEncAlgo(EncryptionConstants.ALGO_ID_KEYTRANSPORT_RSA15); |
| |
| // Build |
| <span class="fc" id="L408"> encrKeyBuilder.prepare(doc, crypto);</span> |
| |
| // Extract the base64 encoded secret value |
| <span class="fc" id="L411"> byte[] tempKey = new byte[keysize / 8];</span> |
| <span class="fc" id="L412"> System.arraycopy(encrKeyBuilder.getEphemeralKey(), 0, tempKey,</span> |
| 0, keysize / 8); |
| |
| <span class="fc" id="L415"> data.setEphmeralKey(tempKey);</span> |
| |
| // Extract the Encryptedkey DOM element |
| <span class="fc" id="L418"> encryptedKeyElem = encrKeyBuilder.getEncryptedKeyElement();</span> |
| <span class="nc" id="L419"> } catch (WSSecurityException e) {</span> |
| <span class="nc" id="L420"> throw new TrustException(</span> |
| "errorInBuildingTheEncryptedKeyForPrincipal", |
| new String[]{serviceCert.getSubjectDN().getName()}, |
| e); |
| <span class="fc" id="L424"> }</span> |
| |
| <span class="fc" id="L426"> keyInfoElem = doc.createElementNS(WSConstants.SIG_NS,</span> |
| "ds:KeyInfo"); |
| <span class="fc" id="L428"> ((OMElement) encryptedKeyElem).declareNamespace(WSConstants.SIG_NS,</span> |
| WSConstants.SIG_PREFIX); |
| <span class="fc" id="L430"> ((OMElement) encryptedKeyElem).declareNamespace(WSConstants.ENC_NS,</span> |
| WSConstants.ENC_PREFIX); |
| |
| <span class="fc" id="L433"> keyInfoElem.appendChild(encryptedKeyElem);</span> |
| |
| <span class="fc" id="L435"> }</span> |
| |
| // If it is a public Key |
| <span class="pc bpc" id="L438" title="1 of 2 branches missed."> else if(data.getKeyType().endsWith(RahasConstants.KEY_TYPE_PUBLIC_KEY)){</span> |
| try { |
| <span class="fc" id="L440"> String subjectNameId = data.getPrincipal().getName();</span> |
| |
| //Create NameID and attach it to the subject |
| <span class="fc" id="L443"> NameIDBuilder nb = new NameIDBuilder();</span> |
| <span class="fc" id="L444"> NameID nameID = nb.buildObject();</span> |
| <span class="fc" id="L445"> nameID.setValue(subjectNameId);</span> |
| <span class="fc" id="L446"> nameID.setFormat(NameIdentifier.EMAIL);</span> |
| <span class="fc" id="L447"> subject.setNameID(nameID);</span> |
| |
| |
| // Create the ds:KeyValue element with the ds:X509Data |
| <span class="fc" id="L451"> X509Certificate clientCert = data.getClientCert();</span> |
| |
| <span class="pc bpc" id="L453" title="1 of 2 branches missed."> if (clientCert == null) {</span> |
| // TODO are we always looking up by alias ? Dont we need to lookup by any other attribute ? |
| <span class="nc" id="L455"> clientCert = CommonUtil.getCertificateByAlias(crypto, data.getPrincipal().getName());</span> |
| } |
| |
| <span class="fc" id="L458"> byte[] clientCertBytes = clientCert.getEncoded();</span> |
| |
| <span class="fc" id="L460"> String base64Cert = Base64.encode(clientCertBytes);</span> |
| |
| <span class="fc" id="L462"> Text base64CertText = doc.createTextNode(base64Cert);</span> |
| |
| //----------------------------------------- |
| |
| <span class="fc" id="L466"> Element x509CertElem = doc.createElementNS(WSConstants.SIG_NS,</span> |
| "ds:X509Certificate"); |
| <span class="fc" id="L468"> x509CertElem.appendChild(base64CertText);</span> |
| <span class="fc" id="L469"> Element x509DataElem = doc.createElementNS(WSConstants.SIG_NS,</span> |
| "ds:X509Data"); |
| <span class="fc" id="L471"> x509DataElem.appendChild(x509CertElem);</span> |
| |
| |
| <span class="pc bpc" id="L474" title="1 of 2 branches missed."> if (x509DataElem != null) {</span> |
| <span class="fc" id="L475"> keyInfoElem = doc.createElementNS(WSConstants.SIG_NS, "ds:KeyInfo");</span> |
| <span class="fc" id="L476"> ((OMElement) x509DataElem).declareNamespace(</span> |
| WSConstants.SIG_NS, WSConstants.SIG_PREFIX); |
| <span class="fc" id="L478"> keyInfoElem.appendChild(x509DataElem);</span> |
| } |
| |
| <span class="nc" id="L481"> } catch (Exception e) {</span> |
| <span class="nc" id="L482"> throw new TrustException("samlAssertionCreationError", e);</span> |
| <span class="fc" id="L483"> }</span> |
| } |
| |
| // Unmarshall the keyInfo DOM element into an XMLObject |
| <span class="fc" id="L487"> String keyInfoElementString = keyInfoElem.toString();</span> |
| <span class="fc" id="L488"> DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();</span> |
| <span class="fc" id="L489"> documentBuilderFactory.setNamespaceAware(true);</span> |
| <span class="fc" id="L490"> DocumentBuilder docBuilder = documentBuilderFactory.newDocumentBuilder();</span> |
| <span class="fc" id="L491"> Document document = docBuilder.parse(new ByteArrayInputStream(keyInfoElementString.trim().getBytes()));</span> |
| <span class="fc" id="L492"> Element element = document.getDocumentElement();</span> |
| |
| |
| // Get appropriate unmarshaller |
| <span class="fc" id="L496"> UnmarshallerFactory unmarshallerFactory = Configuration.getUnmarshallerFactory();</span> |
| <span class="fc" id="L497"> Unmarshaller unmarshaller = unmarshallerFactory.getUnmarshaller(element);</span> |
| |
| // Unmarshall using the document root element, an keyInfo element in this case |
| <span class="fc" id="L500"> XMLObject keyInfoElement = null;</span> |
| try { |
| <span class="fc" id="L502"> keyInfoElement = unmarshaller.unmarshall(element);</span> |
| <span class="nc" id="L503"> } catch (UnmarshallingException e) {</span> |
| <span class="nc" id="L504"> throw new TrustException("Error unmarshalling KeyInfo Element", e);</span> |
| <span class="fc" id="L505"> }</span> |
| |
| |
| //Build the Subject Confirmation |
| <span class="fc" id="L509"> SAMLObjectBuilder<SubjectConfirmation> subjectConfirmationBuilder =</span> |
| (SAMLObjectBuilder<SubjectConfirmation>) builderFactory.getBuilder(SubjectConfirmation.DEFAULT_ELEMENT_NAME); |
| <span class="fc" id="L511"> SubjectConfirmation subjectConfirmation = subjectConfirmationBuilder.buildObject();</span> |
| |
| //Set the subject Confirmation method |
| <span class="fc" id="L514"> subjectConfirmation.setMethod("urn:oasis:names:tc:SAML:2.0:cm:holder-of-key");</span> |
| |
| <span class="fc" id="L516"> SAMLObjectBuilder<KeyInfoConfirmationDataType> keyInfoSubjectConfirmationDataBuilder =</span> |
| (SAMLObjectBuilder<KeyInfoConfirmationDataType>) builderFactory.getBuilder(KeyInfoConfirmationDataType.TYPE_NAME); |
| |
| //Build the subject confirmation data element |
| <span class="fc" id="L520"> KeyInfoConfirmationDataType scData = keyInfoSubjectConfirmationDataBuilder.</span> |
| buildObject(SubjectConfirmationData.DEFAULT_ELEMENT_NAME, KeyInfoConfirmationDataType.TYPE_NAME); |
| |
| //Set the keyInfo element |
| <span class="fc" id="L524"> scData.getKeyInfos().add(keyInfoElement);</span> |
| |
| // Set the validity period |
| <span class="fc" id="L527"> scData.setNotBefore(creationTime);</span> |
| <span class="fc" id="L528"> scData.setNotOnOrAfter(expirationTime);</span> |
| |
| //Set the subject confirmation data |
| <span class="fc" id="L531"> subjectConfirmation.setSubjectConfirmationData(scData);</span> |
| |
| //set the subject confirmation |
| <span class="fc" id="L534"> subject.getSubjectConfirmations().add(subjectConfirmation);</span> |
| |
| <span class="fc" id="L536"> log.debug("SAML2.0 subject is constructed successfully.");</span> |
| <span class="fc" id="L537"> return subject;</span> |
| } |
| |
| /** |
| * This method creates a subject element with the bearer subject confirmation method |
| * @param data RahasData element |
| * @return SAML 2.0 Subject element with Bearer subject confirmation |
| */ |
| private Subject createSubjectWithBearerSC(RahasData data){ |
| <span class="fc" id="L546"> XMLObjectBuilderFactory builderFactory = Configuration.getBuilderFactory();</span> |
| <span class="fc" id="L547"> SAMLObjectBuilder<Subject> subjectBuilder =</span> |
| (SAMLObjectBuilder<Subject>) builderFactory.getBuilder(Subject.DEFAULT_ELEMENT_NAME); |
| <span class="fc" id="L549"> Subject subject = subjectBuilder.buildObject();</span> |
| |
| //Create NameID and attach it to the subject |
| <span class="fc" id="L552"> NameID nameID = new NameIDBuilder().buildObject();</span> |
| <span class="fc" id="L553"> nameID.setValue(data.getPrincipal().getName());</span> |
| <span class="fc" id="L554"> nameID.setFormat(NameIdentifier.EMAIL);</span> |
| <span class="fc" id="L555"> subject.setNameID(nameID);</span> |
| |
| //Build the Subject Confirmation |
| <span class="fc" id="L558"> SAMLObjectBuilder<SubjectConfirmation> subjectConfirmationBuilder =</span> |
| (SAMLObjectBuilder<SubjectConfirmation>) builderFactory.getBuilder(SubjectConfirmation.DEFAULT_ELEMENT_NAME); |
| <span class="fc" id="L560"> SubjectConfirmation subjectConfirmation = subjectConfirmationBuilder.buildObject();</span> |
| |
| //Set the subject Confirmation method |
| <span class="fc" id="L563"> subjectConfirmation.setMethod("urn:oasis:names:tc:SAML:2.0:cm:bearer");</span> |
| |
| <span class="fc" id="L565"> subject.getSubjectConfirmations().add(subjectConfirmation);</span> |
| <span class="fc" id="L566"> return subject;</span> |
| } |
| |
| |
| /** |
| * 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. |
| <span class="fc" id="L580"> Signature signature = (Signature) buildXMLObject(Signature.DEFAULT_ELEMENT_NAME);</span> |
| <span class="fc" id="L581"> signature.setSigningCredential(cred);</span> |
| <span class="fc" id="L582"> signature.setSignatureAlgorithm(cred.getSignatureAlgorithm());</span> |
| <span class="fc" id="L583"> signature.setCanonicalizationAlgorithm(Canonicalizer.ALGO_ID_C14N_EXCL_OMIT_COMMENTS);</span> |
| |
| //Build the KeyInfo element and set the certificate |
| try { |
| <span class="fc" id="L587"> KeyInfo keyInfo = (KeyInfo) buildXMLObject(KeyInfo.DEFAULT_ELEMENT_NAME);</span> |
| <span class="fc" id="L588"> X509Data data = (X509Data) buildXMLObject(X509Data.DEFAULT_ELEMENT_NAME);</span> |
| <span class="fc" id="L589"> org.opensaml.xml.signature.X509Certificate cert = (org.opensaml.xml.signature.X509Certificate) buildXMLObject(org.opensaml.xml.signature.X509Certificate.DEFAULT_ELEMENT_NAME);</span> |
| <span class="fc" id="L590"> String value = org.apache.xml.security.utils.Base64.encode(cred.getEntityCertificate().getEncoded());</span> |
| <span class="fc" id="L591"> cert.setValue(value);</span> |
| <span class="fc" id="L592"> data.getX509Certificates().add(cert);</span> |
| <span class="fc" id="L593"> keyInfo.getX509Datas().add(data);</span> |
| <span class="fc" id="L594"> signature.setKeyInfo(keyInfo);</span> |
| <span class="fc" id="L595"> assertion.setSignature(signature);</span> |
| <span class="fc" id="L596"> signatureList.add(signature);</span> |
| |
| //Marshall and Sign |
| <span class="fc" id="L599"> MarshallerFactory marshallerFactory = org.opensaml.xml.Configuration.getMarshallerFactory();</span> |
| <span class="fc" id="L600"> Marshaller marshaller = marshallerFactory.getMarshaller(assertion);</span> |
| <span class="fc" id="L601"> marshaller.marshall(assertion);</span> |
| <span class="fc" id="L602"> org.apache.xml.security.Init.init();</span> |
| <span class="fc" id="L603"> Signer.signObjects(signatureList);</span> |
| <span class="nc" id="L604"> } catch (CertificateEncodingException e) {</span> |
| <span class="nc" id="L605"> throw new TrustException("Error in setting the signature", e);</span> |
| <span class="nc" id="L606"> } catch (SignatureException e) {</span> |
| <span class="nc" id="L607"> throw new TrustException("errorMarshellingOrSigning", e);</span> |
| <span class="nc" id="L608"> } catch (MarshallingException e) {</span> |
| <span class="nc" id="L609"> throw new TrustException("errorMarshellingOrSigning", e);</span> |
| <span class="fc" id="L610"> }</span> |
| |
| <span class="fc" id="L612"> log.debug("SAML2.0 assertion is marshalled and signed..");</span> |
| |
| <span class="fc" id="L614"> return assertion;</span> |
| } |
| |
| |
| /** |
| * This method is used to build the assertion elements |
| * @param objectQName |
| * @return |
| * @throws Exception |
| */ |
| protected static XMLObject buildXMLObject(QName objectQName) throws Exception { |
| <span class="fc" id="L625"> XMLObjectBuilder builder = org.opensaml.xml.Configuration.getBuilderFactory().getBuilder(objectQName);</span> |
| <span class="pc bpc" id="L626" title="1 of 2 branches missed."> if (builder == null) {</span> |
| <span class="nc" id="L627"> throw new TrustException("Unable to retrieve builder for object QName "</span> |
| + objectQName); |
| } |
| <span class="fc" id="L630"> return builder.buildObject(objectQName.getNamespaceURI(), objectQName.getLocalPart(),</span> |
| 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 { |
| |
| <span class="fc" id="L644"> SignKeyHolder signKeyHolder = new SignKeyHolder();</span> |
| |
| try { |
| <span class="fc" id="L647"> X509Certificate[] issuerCerts = CommonUtil.getCertificatesByAlias(crypto,config.issuerKeyAlias);</span> |
| |
| <span class="fc" id="L649"> String sigAlgo = XMLSignature.ALGO_ID_SIGNATURE_RSA;</span> |
| <span class="fc" id="L650"> String pubKeyAlgo = issuerCerts[0].getPublicKey().getAlgorithm();</span> |
| <span class="pc bpc" id="L651" title="1 of 2 branches missed."> if (pubKeyAlgo.equalsIgnoreCase("DSA")) {</span> |
| <span class="nc" id="L652"> sigAlgo = XMLSignature.ALGO_ID_SIGNATURE_DSA;</span> |
| } |
| <span class="fc" id="L654"> java.security.Key issuerPK = crypto.getPrivateKey(</span> |
| config.issuerKeyAlias, config.issuerKeyPassword); |
| |
| <span class="fc" id="L657"> signKeyHolder.setIssuerCerts(issuerCerts);</span> |
| <span class="fc" id="L658"> signKeyHolder.setIssuerPK((PrivateKey) issuerPK);</span> |
| <span class="fc" id="L659"> signKeyHolder.setSignatureAlgorithm(sigAlgo);</span> |
| |
| <span class="nc" id="L661"> } catch (Exception e) {</span> |
| <span class="nc" id="L662"> throw new TrustException("Error creating issuer signature");</span> |
| <span class="fc" id="L663"> }</span> |
| |
| <span class="fc" id="L665"> log.debug("SignKeyHolder object is created with the credentials..");</span> |
| |
| <span class="fc" id="L667"> return signKeyHolder;</span> |
| } |
| |
| /** |
| * Creates the Attribute Statement |
| * @param data |
| * @param config |
| * @return |
| * @throws SAMLException |
| */ |
| private AttributeStatement createAttributeStatement(RahasData data, SAMLTokenIssuerConfig config) throws SAMLException, TrustException { |
| |
| <span class="fc" id="L679"> XMLObjectBuilderFactory builderFactory = Configuration.getBuilderFactory();</span> |
| <span class="fc" id="L680"> SAMLObjectBuilder<AttributeStatement> attrStmtBuilder =</span> |
| (SAMLObjectBuilder<AttributeStatement>) builderFactory.getBuilder(AttributeStatement.DEFAULT_ELEMENT_NAME); |
| |
| <span class="fc" id="L683"> SAMLObjectBuilder<Attribute> attrBuilder =</span> |
| (SAMLObjectBuilder<Attribute>) builderFactory.getBuilder(Attribute.DEFAULT_ELEMENT_NAME); |
| |
| <span class="fc" id="L686"> AttributeStatement attrstmt = attrStmtBuilder.buildObject();</span> |
| |
| <span class="fc" id="L688"> Attribute[] attributes = null;</span> |
| |
| //Call the attribute callback handlers to get any attributes if exists |
| <span class="pc bpc" id="L691" title="1 of 2 branches missed."> if (config.getCallbackHandler() != null) {</span> |
| <span class="nc" id="L692"> SAMLAttributeCallback cb = new SAMLAttributeCallback(data);</span> |
| <span class="nc" id="L693"> SAMLCallbackHandler handler = config.getCallbackHandler();</span> |
| <span class="nc" id="L694"> handler.handle(cb);</span> |
| <span class="nc" id="L695"> attributes = cb.getSAML2Attributes();</span> |
| <span class="nc" id="L696"> }</span> |
| <span class="pc bpc" id="L697" title="3 of 4 branches missed."> else if (config.getCallbackHandlerName() != null</span> |
| && config.getCallbackHandlerName().trim().length() > 0) { |
| <span class="nc" id="L699"> SAMLAttributeCallback cb = new SAMLAttributeCallback(data);</span> |
| <span class="nc" id="L700"> SAMLCallbackHandler handler = null;</span> |
| <span class="nc" id="L701"> MessageContext msgContext = data.getInMessageContext();</span> |
| <span class="nc" id="L702"> ClassLoader classLoader = msgContext.getAxisService().getClassLoader();</span> |
| <span class="nc" id="L703"> Class cbClass = null;</span> |
| try { |
| <span class="nc" id="L705"> cbClass = Loader.loadClass(classLoader, config.getCallbackHandlerName());</span> |
| <span class="nc" id="L706"> } catch (ClassNotFoundException e) {</span> |
| <span class="nc" id="L707"> throw new TrustException("cannotLoadPWCBClass", new String[]{config</span> |
| .getCallbackHandlerName()}, e); |
| <span class="nc" id="L709"> }</span> |
| try { |
| <span class="nc" id="L711"> handler = (SAMLCallbackHandler) cbClass.newInstance();</span> |
| <span class="nc" id="L712"> } catch (java.lang.Exception e) {</span> |
| <span class="nc" id="L713"> throw new TrustException("cannotCreatePWCBInstance", new String[]{config</span> |
| .getCallbackHandlerName()}, e); |
| <span class="nc" id="L715"> }</span> |
| <span class="nc" id="L716"> handler.handle(cb);</span> |
| <span class="nc" id="L717"> attributes = cb.getSAML2Attributes();</span> |
| // else add the attribute with a default value |
| <span class="nc" id="L719"> } </span> |
| |
| //else add the attribute with a default value |
| else { |
| <span class="fc" id="L723"> Attribute attribute = attrBuilder.buildObject();</span> |
| <span class="fc" id="L724"> attribute.setName("Name");</span> |
| <span class="fc" id="L725"> attribute.setNameFormat("urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified");</span> |
| |
| <span class="fc" id="L727"> XSStringBuilder attributeValueBuilder = (XSStringBuilder) builderFactory</span> |
| .getBuilder(XSString.TYPE_NAME); |
| |
| <span class="fc" id="L730"> XSString stringValue = attributeValueBuilder.buildObject(</span> |
| AttributeValue.DEFAULT_ELEMENT_NAME, XSString.TYPE_NAME); |
| <span class="fc" id="L732"> stringValue.setValue("Colombo/Rahas");</span> |
| <span class="fc" id="L733"> attribute.getAttributeValues().add(stringValue);</span> |
| <span class="fc" id="L734"> attributes = new Attribute[1];</span> |
| <span class="fc" id="L735"> attributes[0] = attribute;</span> |
| } |
| //add attributes to the attribute statement |
| <span class="fc" id="L738"> attrstmt.getAttributes().addAll(Arrays.asList(attributes));</span> |
| |
| <span class="fc" id="L740"> log.debug("SAML2.0 attribute statement is constructed successfully.");</span> |
| |
| <span class="fc" id="L742"> return attrstmt;</span> |
| } |
| |
| /** |
| * build the authentication statement |
| * @param data |
| * @return |
| */ |
| private AuthnStatement createAuthnStatement(RahasData data) { |
| <span class="fc" id="L751"> XMLObjectBuilderFactory builderFactory = Configuration.getBuilderFactory();</span> |
| <span class="fc" id="L752"> MessageContext inMsgCtx = data.getInMessageContext();</span> |
| |
| <span class="fc" id="L754"> SAMLObjectBuilder<AuthnStatement> authStmtBuilder =</span> |
| (SAMLObjectBuilder<AuthnStatement>) builderFactory.getBuilder(AuthnStatement.DEFAULT_ELEMENT_NAME); |
| |
| //build the auth stmt |
| <span class="fc" id="L758"> AuthnStatement authStmt = authStmtBuilder.buildObject();</span> |
| |
| // set the authn instance |
| <span class="fc" id="L761"> authStmt.setAuthnInstant(new DateTime());</span> |
| |
| <span class="fc" id="L763"> SAMLObjectBuilder<AuthnContext> authCtxBuilder =</span> |
| (SAMLObjectBuilder<AuthnContext>) builderFactory.getBuilder(AuthnContext.DEFAULT_ELEMENT_NAME); |
| <span class="fc" id="L765"> AuthnContext authContext = authCtxBuilder.buildObject();</span> |
| |
| <span class="fc" id="L767"> SAMLObjectBuilder<AuthnContextClassRef> authCtxClassRefBuilder =</span> |
| (SAMLObjectBuilder<AuthnContextClassRef>) builderFactory.getBuilder(AuthnContextClassRef.DEFAULT_ELEMENT_NAME); |
| <span class="fc" id="L769"> AuthnContextClassRef authCtxClassRef = authCtxClassRefBuilder.buildObject();</span> |
| |
| //if username/password based authn |
| <span class="pc bpc" id="L772" title="1 of 2 branches missed."> if (inMsgCtx.getProperty(RahasConstants.USERNAME) != null) {</span> |
| <span class="nc" id="L773"> authCtxClassRef.setAuthnContextClassRef(AuthnContext.PASSWORD_AUTHN_CTX);</span> |
| } |
| //if X.509 cert based authn |
| <span class="pc bpc" id="L776" title="1 of 2 branches missed."> else if (inMsgCtx.getProperty(RahasConstants.X509_CERT) != null) {</span> |
| <span class="nc" id="L777"> authCtxClassRef.setAuthnContextClassRef(AuthnContext.X509_AUTHN_CTX);</span> |
| } |
| |
| <span class="fc" id="L780"> authContext.setAuthnContextClassRef(authCtxClassRef);</span> |
| <span class="fc" id="L781"> authStmt.setAuthnContext(authContext);</span> |
| |
| <span class="fc" id="L783"> log.debug("SAML2.0 authentication statement is constructed successfully.");</span> |
| |
| <span class="fc" id="L785"> return authStmt;</span> |
| } |
| |
| |
| public String getResponseAction(RahasData data) throws TrustException { |
| <span class="fc" id="L790"> return null;</span> |
| } |
| |
| public void setConfigurationFile(String configFile) { |
| <span class="fc" id="L794"> this.configFile = configFile;</span> |
| <span class="fc" id="L795"> }</span> |
| |
| public void setConfigurationElement(OMElement configElement) { |
| <span class="fc" id="L798"> this.configElement = configElement;</span> |
| <span class="fc" id="L799"> }</span> |
| |
| public void setConfigurationParamName(String configParamName) { |
| <span class="fc" id="L802"> this.configParamName = configParamName;</span> |
| <span class="fc" id="L803"> }</span> |
| |
| } |
| </pre><div class="footer"><span class="right">Created with <a href="http://www.eclemma.org/jacoco">JaCoCo</a> 0.6.1.201212231917</span></div></body></html> |