<?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>SAMLTokenIssuer.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> &gt; <a href="index.html" class="el_package">org.apache.rahas.impl</a> &gt; <span class="el_source">SAMLTokenIssuer.java</span></div><h1>SAMLTokenIssuer.java</h1><pre class="source lang-java linenums">/*
 * Copyright 2004,2005 The Apache Software Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
 * 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 &quot;AS IS&quot; 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.soap.SOAPEnvelope;
import org.apache.axis2.context.MessageContext;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.rahas.RahasConstants;
import org.apache.rahas.RahasData;
import org.apache.rahas.Token;
import org.apache.rahas.TokenIssuer;
import org.apache.rahas.TrustException;
import org.apache.rahas.TrustUtil;
import org.apache.rahas.impl.util.*;
import org.apache.ws.security.WSSecurityException;
import org.apache.ws.security.WSUsernameTokenPrincipal;
import org.apache.ws.security.components.crypto.Crypto;
import org.apache.ws.security.util.Loader;
import org.apache.ws.security.util.XmlSchemaDateFormat;

import org.joda.time.DateTime;
import org.opensaml.common.SAMLException;
import org.opensaml.saml1.core.*;
import org.opensaml.xml.signature.KeyInfo;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

import java.security.Principal;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * Issuer to issue SAMl tokens
 */
<span class="fc" id="L57">public class SAMLTokenIssuer implements TokenIssuer {</span>

    private String configParamName;

    private OMElement configElement;

    private String configFile;

<span class="fc" id="L65">    private static final Log log = LogFactory.getLog(SAMLTokenIssuer.class);</span>

    public SOAPEnvelope issue(RahasData data) throws TrustException {
<span class="fc" id="L68">        MessageContext inMsgCtx = data.getInMessageContext();</span>

<span class="fc" id="L70">        SAMLTokenIssuerConfig tokenIssuerConfiguration = CommonUtil.getTokenIssuerConfiguration(this.configElement,</span>
                    this.configFile, inMsgCtx.getParameter(this.configParamName));

<span class="pc bpc" id="L73" title="1 of 2 branches missed.">        if (tokenIssuerConfiguration == null) {</span>

<span class="nc bnc" id="L75" title="All 2 branches missed.">            if (log.isDebugEnabled()) {</span>
                String parameterName;
<span class="nc bnc" id="L77" title="All 2 branches missed.">                if (this.configElement != null) {</span>
<span class="nc" id="L78">                    parameterName = &quot;OMElement - &quot; + this.configElement.toString();</span>
<span class="nc bnc" id="L79" title="All 2 branches missed.">                } else if (this.configFile != null) {</span>
<span class="nc" id="L80">                    parameterName = &quot;File - &quot; + this.configFile;</span>
<span class="nc bnc" id="L81" title="All 2 branches missed.">                } else if (this.configParamName != null) {</span>
<span class="nc" id="L82">                    parameterName = &quot;With message context parameter name - &quot; + this.configParamName;</span>
                } else {
<span class="nc" id="L84">                    parameterName = &quot;No method to build configurations&quot;;</span>
                }

<span class="nc" id="L87">                log.debug(&quot;Unable to build token configurations, &quot; + parameterName);</span>
            }

<span class="nc" id="L90">            throw new TrustException(&quot;configurationIsNull&quot;);</span>
        }

<span class="fc" id="L93">        SOAPEnvelope env = TrustUtil.createSOAPEnvelope(inMsgCtx</span>
                .getEnvelope().getNamespace().getNamespaceURI());

<span class="fc" id="L96">        Crypto crypto = tokenIssuerConfiguration.getIssuerCrypto(inMsgCtx</span>
                    .getAxisService().getClassLoader());

        // Creation and expiration times
<span class="fc" id="L100">        DateTime creationTime = new DateTime();</span>
<span class="fc" id="L101">        DateTime expirationTime = new DateTime(creationTime.getMillis() + tokenIssuerConfiguration.getTtl());</span>

        // Get the document
<span class="fc" id="L104">        Document doc = ((Element) env).getOwnerDocument();</span>

        // Get the key size and create a new byte array of that size
<span class="fc" id="L107">        int keySize = data.getKeysize();</span>

<span class="pc bpc" id="L109" title="1 of 2 branches missed.">        keySize = (keySize == -1) ? tokenIssuerConfiguration.getKeySize() : keySize;</span>

        /*
         * Find the KeyType If the KeyType is SymmetricKey or PublicKey,
         * issue a SAML HoK assertion. - In the case of the PublicKey, in
         * coming security header MUST contain a certificate (maybe via
         * signature)
         * 
         * If the KeyType is Bearer then issue a Bearer assertion
         * 
         * If the key type is missing we will issue a HoK assertion
         */

<span class="fc" id="L122">        String keyType = data.getKeyType();</span>
        Assertion assertion;
<span class="pc bpc" id="L124" title="1 of 2 branches missed.">        if (keyType == null) {</span>
<span class="nc" id="L125">            throw new TrustException(TrustException.INVALID_REQUEST,</span>
                    new String[] { &quot;Requested KeyType is missing&quot; });
        }

<span class="fc bfc" id="L129" title="All 4 branches covered.">        if (keyType.endsWith(RahasConstants.KEY_TYPE_SYMM_KEY)</span>
                || keyType.endsWith(RahasConstants.KEY_TYPE_PUBLIC_KEY)) {
<span class="fc" id="L131">            assertion = createHoKAssertion(tokenIssuerConfiguration, doc, crypto,</span>
                    creationTime, expirationTime, data);
<span class="pc bpc" id="L133" title="1 of 2 branches missed.">        } else if (keyType.endsWith(RahasConstants.KEY_TYPE_BEARER)) {</span>
<span class="fc" id="L134">            assertion = createBearerAssertion(tokenIssuerConfiguration, doc, crypto,</span>
                    creationTime, expirationTime, data);
        } else {
<span class="nc" id="L137">            throw new TrustException(&quot;unsupportedKeyType&quot;);</span>
        }

        OMElement rstrElem;
<span class="fc" id="L141">        int wstVersion = data.getVersion();</span>
<span class="fc bfc" id="L142" title="All 2 branches covered.">        if (RahasConstants.VERSION_05_02 == wstVersion) {</span>
<span class="fc" id="L143">            rstrElem = TrustUtil.createRequestSecurityTokenResponseElement(</span>
                    wstVersion, env.getBody());
        } else {
<span class="fc" id="L146">            OMElement rstrcElem = TrustUtil</span>
                    .createRequestSecurityTokenResponseCollectionElement(
                            wstVersion, env.getBody());
<span class="fc" id="L149">            rstrElem = TrustUtil.createRequestSecurityTokenResponseElement(</span>
                    wstVersion, rstrcElem);
        }

<span class="fc" id="L153">        TrustUtil.createTokenTypeElement(wstVersion, rstrElem).setText(</span>
                RahasConstants.TOK_TYPE_SAML_10);

<span class="fc bfc" id="L156" title="All 2 branches covered.">        if (keyType.endsWith(RahasConstants.KEY_TYPE_SYMM_KEY)) {</span>
<span class="fc" id="L157">            TrustUtil.createKeySizeElement(wstVersion, rstrElem, keySize);</span>
        }

<span class="pc bpc" id="L160" title="1 of 2 branches missed.">        if (tokenIssuerConfiguration.isAddRequestedAttachedRef()) {</span>
<span class="fc" id="L161">            TrustUtil.createRequestedAttachedRef(rstrElem, assertion.getID(),wstVersion);</span>
        }

<span class="pc bpc" id="L164" title="1 of 2 branches missed.">        if (tokenIssuerConfiguration.isAddRequestedUnattachedRef()) {</span>
<span class="fc" id="L165">            TrustUtil.createRequestedUnattachedRef(rstrElem, assertion.getID(),wstVersion);</span>
        }

<span class="fc bfc" id="L168" title="All 2 branches covered.">        if (data.getAppliesToAddress() != null) {</span>
<span class="fc" id="L169">            TrustUtil.createAppliesToElement(rstrElem, data</span>
                    .getAppliesToAddress(), data.getAddressingNs());
        }

        // Use GMT time in milliseconds
<span class="fc" id="L174">        DateFormat zulu = new XmlSchemaDateFormat();</span>

        // Add the Lifetime element
<span class="fc" id="L177">        TrustUtil.createLifetimeElement(wstVersion, rstrElem, zulu</span>
                .format(creationTime.toDate()), zulu.format(expirationTime.toDate()));

        // Create the RequestedSecurityToken element and add the SAML token
        // to it
<span class="fc" id="L182">        OMElement reqSecTokenElem = TrustUtil</span>
                .createRequestedSecurityTokenElement(wstVersion, rstrElem);
        Token assertionToken;
        //try {
<span class="fc" id="L186">            Node tempNode = assertion.getDOM();</span>
<span class="fc" id="L187">            reqSecTokenElem.addChild((OMNode) ((Element) rstrElem)</span>
                    .getOwnerDocument().importNode(tempNode, true));

            // Store the token
<span class="fc" id="L191">            assertionToken = new Token(assertion.getID(),</span>
                    (OMElement) assertion.getDOM(), creationTime.toDate(),
                    expirationTime.toDate());

            // At this point we definitely have the secret
            // Otherwise it should fail with an exception earlier
<span class="fc" id="L197">            assertionToken.setSecret(data.getEphmeralKey());</span>
<span class="fc" id="L198">            TrustUtil.getTokenStore(inMsgCtx).add(assertionToken);</span>

       /* } catch (SAMLException e) {
            throw new TrustException(&quot;samlConverstionError&quot;, e);
        }*/

<span class="pc bpc" id="L204" title="1 of 4 branches missed.">        if (keyType.endsWith(RahasConstants.KEY_TYPE_SYMM_KEY)</span>
                &amp;&amp; tokenIssuerConfiguration.getKeyComputation() != SAMLTokenIssuerConfig.KeyComputation.KEY_COMP_USE_REQ_ENT) {

            // Add the RequestedProofToken
<span class="fc" id="L208">            TokenIssuerUtil.handleRequestedProofToken(data, wstVersion,</span>
                    tokenIssuerConfiguration, rstrElem, assertionToken, doc);
        }

<span class="fc" id="L212">        return env;</span>
    }



    private Assertion createBearerAssertion(SAMLTokenIssuerConfig config,
                                            Document doc, Crypto crypto, DateTime creationTime,
                                            DateTime expirationTime, RahasData data) throws TrustException {

<span class="fc" id="L221">        Principal principal = data.getPrincipal();</span>
        Assertion assertion;
        // In the case where the principal is a UT
<span class="pc bpc" id="L224" title="1 of 2 branches missed.">        if (principal instanceof WSUsernameTokenPrincipal) {</span>
<span class="fc" id="L225">            NameIdentifier nameId = null;</span>
<span class="pc bpc" id="L226" title="1 of 2 branches missed.">            if (config.getCallbackHandler() != null) {</span>
<span class="nc" id="L227">                SAMLNameIdentifierCallback cb = new SAMLNameIdentifierCallback(data);</span>
<span class="nc" id="L228">                cb.setUserId(principal.getName());</span>
<span class="nc" id="L229">                SAMLCallbackHandler callbackHandler = config.getCallbackHandler();</span>
                try {
<span class="nc" id="L231">                    callbackHandler.handle(cb);</span>
<span class="nc" id="L232">                } catch (SAMLException e) {</span>
<span class="nc" id="L233">                    throw new TrustException(&quot;unableToRetrieveCallbackHandler&quot;, e);</span>
<span class="nc" id="L234">                }</span>
<span class="nc" id="L235">                nameId = cb.getNameId();</span>
<span class="nc" id="L236">            } else {</span>

<span class="fc" id="L238">                nameId = SAMLUtils.createNamedIdentifier(principal.getName(), NameIdentifier.EMAIL);</span>
            }

<span class="fc" id="L241">            assertion = createAuthAssertion(RahasConstants.SAML11_SUBJECT_CONFIRMATION_BEARER,</span>
                    nameId, null, config, crypto, creationTime,
                    expirationTime, data);
<span class="fc" id="L244">            return assertion;</span>
        } else {
<span class="nc" id="L246">            throw new TrustException(&quot;samlUnsupportedPrincipal&quot;,</span>
                    new String[]{principal.getClass().getName()});
        }
    }

    private Assertion createHoKAssertion(SAMLTokenIssuerConfig config,
            Document doc, Crypto crypto, DateTime creationTime,
            DateTime expirationTime, RahasData data) throws TrustException {

<span class="fc bfc" id="L255" title="All 2 branches covered.">        if (data.getKeyType().endsWith(RahasConstants.KEY_TYPE_SYMM_KEY)) {</span>
<span class="fc" id="L256">            X509Certificate serviceCert = null;</span>
            try {

                // TODO what if principal is null ?
<span class="fc" id="L260">                NameIdentifier nameIdentifier = null;</span>
<span class="pc bpc" id="L261" title="1 of 2 branches missed.">                if (data.getPrincipal() != null) {</span>
<span class="fc" id="L262">                    String subjectNameId = data.getPrincipal().getName();</span>
<span class="fc" id="L263">                    nameIdentifier =SAMLUtils.createNamedIdentifier(subjectNameId, NameIdentifier.EMAIL);</span>
                }

                /**
                 * In this case we need to create a KeyInfo similar to following,
                 * *  &lt;KeyInfo xmlns=&quot;http://www.w3.org/2000/09/xmldsig#&quot;&gt;
                 *     &lt;xenc:EncryptedKey xmlns:xenc=&quot;http://www.w3.org/2001/04/xmlenc#&quot;
                 *           ....
                 *     &lt;/xenc:EncryptedKey&gt;
                 *   &lt;/ds:KeyInfo&gt;
                 */

                // Get ApliesTo to figure out which service to issue the token
                // for
<span class="fc" id="L277">                serviceCert = getServiceCert(config, crypto, data</span>
                        .getAppliesToAddress());

                // set keySize
<span class="fc" id="L281">                int keySize = data.getKeysize();</span>
<span class="pc bpc" id="L282" title="1 of 2 branches missed.">                keySize = (keySize != -1) ? keySize : config.getKeySize();</span>

                // Create the encrypted key
<span class="fc" id="L285">                KeyInfo encryptedKeyInfoElement</span>
                        = CommonUtil.getSymmetricKeyBasedKeyInfo(doc, data, serviceCert, keySize,
                        crypto, config.getKeyComputation());

<span class="fc" id="L289">                return this.createAttributeAssertion(data, encryptedKeyInfoElement, nameIdentifier, config,</span>
                    crypto, creationTime, expirationTime);


<span class="nc" id="L293">            } catch (WSSecurityException e) {</span>

<span class="nc bnc" id="L295" title="All 2 branches missed.">                if (serviceCert != null) {</span>
<span class="nc" id="L296">                    throw new TrustException(</span>
                            &quot;errorInBuildingTheEncryptedKeyForPrincipal&quot;,
                            new String[]{serviceCert.getSubjectDN().getName()},
                            e);
                } else {
<span class="nc" id="L301">                    throw new TrustException(</span>
                            &quot;trustedCertNotFoundForEPR&quot;,
                            new String[]{data.getAppliesToAddress()},
                            e);
                }

            }
        } else {
            try {

                /**
                 * In this case we need to create KeyInfo as follows,
                 * &lt;KeyInfo xmlns=&quot;http://www.w3.org/2000/09/xmldsig#&quot;&gt;
                 *   &lt;X509Data xmlns:xenc=&quot;http://www.w3.org/2001/04/xmlenc#&quot;
                 *             xmlns:ds=&quot;http://www.w3.org/2000/09/xmldsig#&quot;&gt;
                 *        &lt;X509Certificate&gt;
                 *              MIICNTCCAZ6gAwIBAgIES343....
                 *           &lt;/X509Certificate&gt;
                 *       &lt;/X509Data&gt;
                 *   &lt;/KeyInfo&gt;
                 */

<span class="fc" id="L323">                String subjectNameId = data.getPrincipal().getName();</span>
                
<span class="fc" id="L325">                NameIdentifier nameId = SAMLUtils.createNamedIdentifier(subjectNameId, NameIdentifier.EMAIL);</span>

                // Create the ds:KeyValue element with the ds:X509Data
<span class="fc" id="L328">                X509Certificate clientCert = data.getClientCert();</span>

<span class="pc bpc" id="L330" title="1 of 2 branches missed.">                if(clientCert == null) {</span>
<span class="nc" id="L331">                    clientCert = CommonUtil.getCertificateByAlias(crypto,data.getPrincipal().getName());;</span>
                }

<span class="fc" id="L334">                KeyInfo keyInfo = CommonUtil.getCertificateBasedKeyInfo(clientCert);</span>

<span class="fc" id="L336">                return this.createAuthAssertion(RahasConstants.SAML11_SUBJECT_CONFIRMATION_HOK, nameId, keyInfo,</span>
                        config, crypto, creationTime, expirationTime, data);
<span class="nc" id="L338">            } catch (Exception e) {</span>
<span class="nc" id="L339">                throw new TrustException(&quot;samlAssertionCreationError&quot;, e);</span>
            }
        }
    }

    /**
     * Uses the &lt;code&gt;wst:AppliesTo&lt;/code&gt; to figure out the certificate to
     * encrypt the secret in the SAML token
     * 
     * @param config Token issuer configuration.
     * @param crypto Crypto properties.
     * @param serviceAddress
     *            The address of the service
     * @return The X509 certificate.
     * @throws org.apache.rahas.TrustException If an error occurred while retrieving certificate from crypto.
     */
    private X509Certificate getServiceCert(SAMLTokenIssuerConfig config,
            Crypto crypto, String serviceAddress) throws TrustException {

        // TODO a duplicate method !!
<span class="pc bpc" id="L359" title="1 of 4 branches missed.">        if (serviceAddress != null &amp;&amp; !&quot;&quot;.equals(serviceAddress)) {</span>
<span class="fc" id="L360">            String alias = (String) config.getTrustedServices().get(serviceAddress);</span>
<span class="pc bpc" id="L361" title="1 of 2 branches missed.">            if (alias != null) {</span>
<span class="fc" id="L362">                return CommonUtil.getCertificateByAlias(crypto,alias);</span>
            } else {
<span class="nc" id="L364">                alias = (String) config.getTrustedServices().get(&quot;*&quot;);</span>
<span class="nc" id="L365">                return CommonUtil.getCertificateByAlias(crypto,alias);</span>
            }
        } else {
<span class="fc" id="L368">            String alias = (String) config.getTrustedServices().get(&quot;*&quot;);</span>
<span class="fc" id="L369">            return CommonUtil.getCertificateByAlias(crypto,alias);</span>
        }

    }

    /**
     * Create the SAML assertion with the secret held in an
     * &lt;code&gt;xenc:EncryptedKey&lt;/code&gt;
     * @param data The Rahas configurations, this is needed to get the callbacks.
     * @param keyInfo OpenSAML KeyInfo representation.
     * @param subjectNameId Principal as an OpenSAML Subject
     * @param config SAML Token issuer configurations.
     * @param crypto To get certificate information.
     * @param notBefore Validity period start.
     * @param notAfter Validity period end
     * @return OpenSAML Assertion object.
     * @throws TrustException If an error occurred while creating the Assertion.
     */
    private Assertion createAttributeAssertion(RahasData data,
                                               KeyInfo keyInfo, NameIdentifier subjectNameId,
                                               SAMLTokenIssuerConfig config,
                                               Crypto crypto, DateTime notBefore, DateTime notAfter) throws TrustException {
        try {

<span class="fc" id="L393">            Subject subject</span>
                    = SAMLUtils.createSubject(subjectNameId, RahasConstants.SAML11_SUBJECT_CONFIRMATION_HOK, keyInfo);

            Attribute[] attributes;

<span class="fc" id="L398">            SAMLCallbackHandler handler = CommonUtil.getSAMLCallbackHandler(config, data);</span>

<span class="fc" id="L400">            SAMLAttributeCallback cb = new SAMLAttributeCallback(data);</span>
<span class="fc bfc" id="L401" title="All 2 branches covered.">            if (handler != null) {</span>
<span class="fc" id="L402">                handler.handle(cb);</span>
<span class="fc" id="L403">                attributes = cb.getAttributes();</span>
            } else {
                //TODO Remove this after discussing
<span class="fc" id="L406">                Attribute attribute = SAMLUtils.createAttribute(&quot;Name&quot;, &quot;https://rahas.apache.org/saml/attrns&quot;,</span>
                        &quot;Colombo/Rahas&quot;);
<span class="fc" id="L408">                attributes = new Attribute[]{attribute};</span>
            }

<span class="fc" id="L411">            AttributeStatement attributeStatement = SAMLUtils.createAttributeStatement(subject, Arrays.asList(attributes));</span>


<span class="fc" id="L414">            List&lt;Statement&gt; attributeStatements = new ArrayList&lt;Statement&gt;();</span>
<span class="fc" id="L415">            attributeStatements.add(attributeStatement);</span>

<span class="fc" id="L417">            Assertion assertion = SAMLUtils.createAssertion(config.getIssuerName(), notBefore,</span>
                    notAfter, attributeStatements);

<span class="fc" id="L420">            SAMLUtils.signAssertion(assertion, crypto, config.getIssuerKeyAlias(), config.getIssuerKeyPassword());</span>

<span class="fc" id="L422">            return assertion;</span>
<span class="nc" id="L423">        } catch (Exception e) {</span>
<span class="nc" id="L424">            throw new TrustException(&quot;samlAssertionCreationError&quot;, e);</span>
        }
    }

    /**
     * Creates an authentication assertion.
     * @param confirmationMethod The confirmation method. (HOK, Bearer ...)
     * @param subjectNameId The principal name.
     * @param keyInfo OpenSAML representation of KeyInfo.
     * @param config Rahas configurations.
     * @param crypto Certificate information.
     * @param notBefore Validity start.
     * @param notAfter Validity end.
     * @param data Other Rahas data.
     * @return An openSAML Assertion.
     * @throws TrustException If an exception occurred while creating the Assertion.
     */
    private Assertion createAuthAssertion(String confirmationMethod,
            NameIdentifier subjectNameId, KeyInfo keyInfo,
            SAMLTokenIssuerConfig config, Crypto crypto, DateTime notBefore,
            DateTime notAfter, RahasData data) throws TrustException {
        try {

<span class="fc" id="L447">            Subject subject = SAMLUtils.createSubject(subjectNameId,confirmationMethod, keyInfo);</span>

<span class="fc" id="L449">            AuthenticationStatement authenticationStatement</span>
                    = SAMLUtils.createAuthenticationStatement(subject, RahasConstants.AUTHENTICATION_METHOD_PASSWORD,
                    notBefore);

<span class="fc" id="L453">            List&lt;Statement&gt; statements = new ArrayList&lt;Statement&gt;();</span>
<span class="pc bpc" id="L454" title="3 of 4 branches missed.">            if (data.getClaimDialect() != null &amp;&amp; data.getClaimElem() != null) {</span>
<span class="nc" id="L455">                Statement attrStatement = createSAMLAttributeStatement(</span>
                        SAMLUtils.createSubject(subject.getNameIdentifier(),
                                confirmationMethod, keyInfo), data, config);
<span class="nc" id="L458">                statements.add(attrStatement);</span>
            }

<span class="fc" id="L461">            statements.add(authenticationStatement);</span>

<span class="fc" id="L463">            Assertion assertion = SAMLUtils.createAssertion(config.getIssuerName(),</span>
                    notBefore, notAfter, statements);

            // Signing the assertion
            // The &lt;ds:Signature&gt;...&lt;/ds:Signature&gt; element appears only after
            // signing.
<span class="fc" id="L469">            SAMLUtils.signAssertion(assertion, crypto, config.getIssuerKeyAlias(), config.getIssuerKeyPassword());</span>

<span class="fc" id="L471">            return assertion;</span>
<span class="nc" id="L472">        } catch (Exception e) {</span>
<span class="nc" id="L473">            throw new TrustException(&quot;samlAssertionCreationError&quot;, e);</span>
        }
    }

    /**
     * {@inheritDoc}
     */
    public String getResponseAction(RahasData data) throws TrustException {
<span class="fc" id="L481">        return TrustUtil.getActionValue(data.getVersion(),</span>
                RahasConstants.RSTR_ACTION_ISSUE);
    }

    /**
     * Create an ephemeral key
     * 
     * @return The generated key as a byte array
     * @throws TrustException
     */
    protected byte[] generateEphemeralKey(int keySize) throws TrustException {
        try {
<span class="nc" id="L493">            SecureRandom random = SecureRandom.getInstance(&quot;SHA1PRNG&quot;);</span>
<span class="nc" id="L494">            byte[] temp = new byte[keySize / 8];</span>
<span class="nc" id="L495">            random.nextBytes(temp);</span>
<span class="nc" id="L496">            return temp;</span>
<span class="nc" id="L497">        } catch (Exception e) {</span>
<span class="nc" id="L498">            throw new TrustException(&quot;Error in creating the ephemeral key&quot;, e);</span>
        }
    }

    /**
     * {@inheritDoc}
     */
    public void setConfigurationFile(String configFile) {
<span class="fc" id="L506">        this.configFile = configFile;</span>

<span class="fc" id="L508">    }</span>
    
    /**
     * {@inheritDoc}
     */
    public void setConfigurationElement(OMElement configElement) {
<span class="fc" id="L514">        this.configElement = configElement;</span>
<span class="fc" id="L515">    }</span>

    /**
     * {@inheritDoc}
     */
    public void setConfigurationParamName(String configParamName) {
<span class="fc" id="L521">        this.configParamName = configParamName;</span>
<span class="fc" id="L522">    }</span>

    private AttributeStatement createSAMLAttributeStatement(Subject subject,
                                                            RahasData rahasData,
                                                            SAMLTokenIssuerConfig config)
            throws TrustException {
<span class="nc" id="L528">        Attribute[] attrs = null;</span>
<span class="nc bnc" id="L529" title="All 2 branches missed.">        if (config.getCallbackHandler() != null) {</span>
<span class="nc" id="L530">            SAMLAttributeCallback cb = new SAMLAttributeCallback(rahasData);</span>
<span class="nc" id="L531">            SAMLCallbackHandler handler = config.getCallbackHandler();</span>
            try {
<span class="nc" id="L533">                handler.handle(cb);</span>
<span class="nc" id="L534">                attrs = cb.getAttributes();</span>
<span class="nc" id="L535">            } catch (SAMLException e) {</span>
<span class="nc" id="L536">                throw new TrustException(&quot;unableToRetrieveCallbackHandler&quot;, e);</span>
<span class="nc" id="L537">            }</span>

<span class="nc bnc" id="L539" title="All 4 branches missed.">        } else if (config.getCallbackHandlerName() != null</span>
                &amp;&amp; config.getCallbackHandlerName().trim().length() &gt; 0) {
<span class="nc" id="L541">            SAMLAttributeCallback cb = new SAMLAttributeCallback(rahasData);</span>
<span class="nc" id="L542">            SAMLCallbackHandler handler = null;</span>
<span class="nc" id="L543">            MessageContext msgContext = rahasData.getInMessageContext();</span>
<span class="nc" id="L544">            ClassLoader classLoader = msgContext.getAxisService().getClassLoader();</span>
<span class="nc" id="L545">            Class cbClass = null;</span>
            try {
<span class="nc" id="L547">                cbClass = Loader.loadClass(classLoader, config.getCallbackHandlerName());</span>
<span class="nc" id="L548">            } catch (ClassNotFoundException e) {</span>
<span class="nc" id="L549">                throw new TrustException(&quot;cannotLoadPWCBClass&quot;,</span>
                        new String[]{config.getCallbackHandlerName()}, e);
<span class="nc" id="L551">            }</span>
            try {
<span class="nc" id="L553">                handler = (SAMLCallbackHandler) cbClass.newInstance();</span>
<span class="nc" id="L554">            } catch (Exception e) {</span>
<span class="nc" id="L555">                throw new TrustException(&quot;cannotCreatePWCBInstance&quot;,</span>
                        new String[]{config.getCallbackHandlerName()}, e);
<span class="nc" id="L557">            }</span>
            try {
<span class="nc" id="L559">                handler.handle(cb);</span>
<span class="nc" id="L560">            } catch (SAMLException e) {</span>
<span class="nc" id="L561">                throw new TrustException(&quot;unableToRetrieveCallbackHandler&quot;, e);</span>
<span class="nc" id="L562">            }</span>
<span class="nc" id="L563">            attrs = cb.getAttributes();</span>
<span class="nc" id="L564">        } else {</span>
            //TODO Remove this after discussing
<span class="nc" id="L566">            Attribute attribute =</span>
                    SAMLUtils.createAttribute(&quot;Name&quot;, &quot;https://rahas.apache.org/saml/attrns&quot;, &quot;Colombo/Rahas&quot;);

<span class="nc" id="L569">            attrs = new Attribute[]{attribute};</span>
        }

<span class="nc" id="L572">        AttributeStatement attributeStatement = SAMLUtils.createAttributeStatement(subject, Arrays.asList(attrs));</span>

<span class="nc" id="L574">        return attributeStatement;</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>