001/**
002 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003 *
004 * Copyright (c) 2006 Sun Microsystems Inc. All Rights Reserved
005 *
006 * The contents of this file are subject to the terms
007 * of the Common Development and Distribution License
008 * (the License). You may not use this file except in
009 * compliance with the License.
010 *
011 * You can obtain a copy of the License at
012 * https://opensso.dev.java.net/public/CDDLv1.0.html or
013 * opensso/legal/CDDLv1.0.txt
014 * See the License for the specific language governing
015 * permission and limitations under the License.
016 *
017 * When distributing Covered Code, include this CDDL
018 * Header Notice in each file and include the License file
019 * at opensso/legal/CDDLv1.0.txt.
020 * If applicable, add the following below the CDDL Header,
021 * with the fields enclosed by brackets [] replaced by
022 * your own identifying information:
023 * "Portions Copyrighted [year] [name of copyright owner]"
024 *
025 * $Id: SecurityAssertion.java,v 1.3 2009/10/01 18:42:07 mallas Exp $
026 *
027 */
028
029package com.sun.identity.liberty.ws.security;
030
031
032import com.sun.identity.shared.xml.XMLUtils;
033import com.sun.identity.shared.DateUtils;
034import com.sun.identity.liberty.ws.common.wsse.WSSEConstants;
035import com.sun.identity.liberty.ws.soapbinding.SOAPBindingConstants;
036import com.sun.identity.saml.assertion.Advice;
037import com.sun.identity.saml.assertion.Assertion;
038import com.sun.identity.saml.assertion.Conditions;
039import com.sun.identity.saml.assertion.Statement;
040import com.sun.identity.saml.assertion.Subject;
041import com.sun.identity.saml.assertion.SubjectConfirmation;
042import com.sun.identity.saml.assertion.SubjectStatement;
043
044import com.sun.identity.saml.common.SAMLConstants;
045import com.sun.identity.saml.common.SAMLException;
046import com.sun.identity.saml.common.SAMLUtils;
047
048import com.sun.identity.saml.xmlsig.XMLSignatureManager;
049
050import java.io.ByteArrayOutputStream;
051
052import java.text.ParseException;
053
054import java.util.Collections;
055import java.util.Date;
056import java.util.HashSet;
057import java.util.Iterator;
058import java.util.List;
059import java.util.Map;
060import java.util.Set;
061
062import org.w3c.dom.Attr;
063import org.w3c.dom.Document;
064import org.w3c.dom.Element;
065import org.w3c.dom.NamedNodeMap;
066import org.w3c.dom.Node;
067import org.w3c.dom.NodeList;
068
069/**
070 * The <code>SecurityAssertion</code> class provides an extension to
071 * <code>Assertion</code> class to support <code>ID-WSF</code>
072 * <code>ResourceAccessStatement</code> and
073 * <code>SessionContextStatement</code>.
074 *
075 * @supported.all.api
076 */
077public class SecurityAssertion extends Assertion {
078    
079    private String verifyingCertAlias = null;
080    
081    /**
082     * This constructor creates a <code>SecurityAssertion</code> object
083     * from a DOM Element.
084     *
085     * @param assertionElement A <code>org.w3c.dom.Element</code> representing
086     *        DOM tree for <code>Assertion</code> object
087     * @throws SAMLException if it could not process the Element properly,
088     *         implying that there is an error in the sender or in the
089     *         element definition.
090     */
091    public SecurityAssertion(org.w3c.dom.Element assertionElement)
092    throws SAMLException {
093        parseAssertionElement(assertionElement);
094    }
095    
096    /**
097     * Constructs <code>SecurityAssertion</code> object with the
098     * <code>assertionID</code>, the issuer, time when assertion issued
099     * and a <code>Set</code> of <code>Statement</code>(s) in the assertion.
100     *
101     * @param assertionID <code>assertionID</code> attribute contained within
102     *        this <code>Assertion</code> if null, an <code>assertionID</code>
103     *        is generated internally.
104     * @param issuer String representing the issuer of this assertion.
105     * @param issueInstant time instant of the issue. It has type
106     *        <code>dateTime</code> which is built in to the W3C XML Schema
107     *        Types specification.if null, current time is used.
108     * @param statements Set of <code>Statement</code> objects within this
109     *        <code>Assertion</code>. It could be of type
110     *        <code>AuthenticationStatement</code>,
111     *        <code>AuthorizationDecisionStatement</code> and
112     *        <code>AttributeStatement</code>. Each Assertion can have multiple
113     *        type of statements in it.
114     * @throws SAMLException issuer is null or the size of statements is 0.
115     */
116    public SecurityAssertion(String assertionID,java.lang.String issuer,
117            Date issueInstant,  Set statements) throws SAMLException {
118        super(assertionID, issuer, issueInstant, statements);
119    }
120    
121    /**
122     * Constructs <code>SecurityAssertion</code> object with the
123     * <code>assertionID</code>, the issuer, time when assertion issued, the
124     * conditions when creating a new assertion and a <code>Set</code> of
125     * <code>Statement</code>(s) in the assertion.
126     *
127     * @param assertionID String representing <code>AssertionID</code>
128     *        contained within this <code>Assertion</code> if null its generated
129     *        internally.
130     * @param issuer String representing the issuer of this assertion.
131     * @param issueInstant time instant of the issue. It has type
132     *        <code>dateTime</code> which is built in to the W3C XML
133     *        Schema Types specification. if null current time is used.
134     * @param conditions <code>Conditions</code> under which the this
135     *        <code>Assertion</code> is valid.
136     * @param statements Set of <code>Statement</code> objects within this
137     *        <code>Assertion</code>. It could be of type
138     *        <code>AuthenticationStatement</code>,
139     *        <code>AuthorizationDecisionStatement</code> and
140     *        <code>AttributeStatement</code>. Each Assertion can have multiple
141     *        type of statements in it.
142     * @throws SAMLException issuer is null or the size of statements is 0.
143     */
144    public SecurityAssertion(String assertionID,java.lang.String issuer,
145            Date issueInstant,  Conditions conditions, Set statements)
146            throws SAMLException {
147        super(assertionID, issuer, issueInstant, conditions, statements);
148    }
149    
150    /**
151     * Constructs <code>SecurityAssertion</code> object with the
152     * <code>assertionID</code>, the issuer, time when assertion issued,
153     * the conditions when creating a new assertion, <code>Advice</code>
154     * applicable to this <code>Assertion</code> and a <code>Set</code> of
155     * <code>Statement</code>(s) in the assertion.
156     *
157     * @param assertionID <code>AssertionID</code> object contained within this
158     *        <code>Assertion</code> if null its generated internally.
159     * @param issuer String representing the issuer of this assertion.
160     * @param issueInstant time instant of the issue. It has type
161     *        <code>dateTime</code> which is built in to the W3C XML Schema
162     *        Types specification. if null current time is used.
163     * @param conditions <code>Conditions</code> under which the this
164     *        <code>Assertion</code> is valid.
165     * @param advice <code>Advice</code> applicable for this
166     *        <code>Assertion</code>.
167     * @param statements Set of <code>Statement</code> objects within this
168     *        <code>Assertion</code>. It could be of type
169     *        <code>AuthenticationStatement</code>,
170     *        <code>AuthorizationDecisionStatement</code> and
171     *        <code>AttributeStatement</code>. Each Assertion can have multiple
172     *        type of statements in it.
173     * @throws SAMLException issuer is null or the size of statements is 0.
174     */
175    public SecurityAssertion(String assertionID,java.lang.String issuer,
176            Date issueInstant,  Conditions conditions, Advice advice,
177            Set statements) throws SAMLException {
178        super(assertionID, issuer, issueInstant, conditions,
179                advice, statements);
180    }
181    
182    /**
183     * Sets the value of the certificate alias.
184     *
185     * @param certAlias the certificate alias.
186     */
187    public void setVerifyingCertAlias(String certAlias) {
188        verifyingCertAlias = certAlias;
189    }
190    
191    /**
192     * Return whether the signature is valid.
193     *
194     * @return true if the signature is valid.
195     */
196    public boolean isSignatureValid() {
197        if (signed & ! validationDone) {
198            try {
199                XMLSignatureManager manager = XMLSignatureManager.getInstance();
200                valid = manager.verifyXMLSignature(xmlString,
201                        ASSERTION_ID_ATTRIBUTE, verifyingCertAlias);
202            } catch (Exception e) {
203                if (SAMLUtils.debug.warningEnabled()) {
204                    SAMLUtils.debug.warning(
205                            "SecurityAssertion.isSignatureValid: "+
206                            " signature validation exception", e);
207                }
208                valid = false;
209            }
210            if (SAMLUtils.debug.messageEnabled()) {
211                SAMLUtils.debug.message("SAMLUtils.checkSignatureValid:"+
212                        " valid = " + valid);
213            }
214            
215            validationDone = true;
216        }
217        return valid;
218    }
219    
220    /**
221     * Determines if the <code>SecurityAssertion</code> contains SAML Bearer
222     * confirmation method.
223     *
224     * @return true if the <code>SecurityAssertion</code> contains SAML Bearer
225     *         confirmation.
226     */
227    public boolean isBearer() {
228        if (_statements == null || _statements.isEmpty()) {
229            return false;
230        }
231        
232        Iterator iter = _statements.iterator();
233        while(iter.hasNext()) {
234            Object statement = iter.next();
235            if (!(statement instanceof SubjectStatement)) {
236                continue;
237            }
238            Subject subject = ((SubjectStatement)statement).getSubject();
239            if (subject == null) {
240                continue;
241            }
242            SubjectConfirmation sc = subject.getSubjectConfirmation();
243            if (sc == null) {
244                continue;
245            }
246            Set confirmationMethods = sc.getConfirmationMethod();
247            if (confirmationMethods == null || confirmationMethods.isEmpty()) {
248                continue;
249            }
250            if (confirmationMethods.contains(
251                    SAMLConstants.CONFIRMATION_METHOD_BEARER)) {
252                return true;
253            }
254        }
255        return false;
256    }
257    
258    /**
259     * Determines if the <code>SecurityAssertion</code> contains SAML Bearer
260     * confirmation method. If it is, return its Subject. Otherwise, return
261     * null.
262     *
263     * @return Subject if the <code>SecurityAssertion</code> contains SAML
264     *         Bearer confirmation.
265     */
266    public Subject getBearerSubject() {
267        if (_statements == null || _statements.isEmpty()) {
268            return null;
269        }
270        
271        Iterator iter = _statements.iterator();
272        while(iter.hasNext()) {
273            Object statement = iter.next();
274            if (!(statement instanceof SubjectStatement)) {
275                continue;
276            }
277            Subject subject = ((SubjectStatement)statement).getSubject();
278            if (subject == null) {
279                continue;
280            }
281            SubjectConfirmation sc = subject.getSubjectConfirmation();
282            if (sc == null) {
283                continue;
284            }
285            Set confirmationMethods = sc.getConfirmationMethod();
286            if (confirmationMethods == null || confirmationMethods.isEmpty()) {
287                continue;
288            }
289            if (confirmationMethods.contains(
290                    SAMLConstants.CONFIRMATION_METHOD_BEARER)) {
291                return subject;
292            }
293        }
294        return null;
295    }
296    
297    /**
298     * Create a String representation of the  element.
299     * @return A string containing the valid XML for this element.
300     * By default name space name is prepended to the element name
301     * example <code>&lt;saml:Assertion&gt;</code>.
302     *
303     * @return the String representation of this element.
304     */
305    public java.lang.String toString() {
306        // call toString() with includeNS true by default and declareNS false
307        return this.toString(true, false);
308    }
309    
310    /**
311     * Creates a String representation of the <code>&lt;Assertion&gt;</code>
312     * element.
313     *
314     * @param includeNS if true prepends all elements by their Namespace
315     *        name example <code>&lt;saml:Assertion&gt</code>;
316     * @param declareNS if true includes the namespace within the generated
317     *        XML.
318     * @return A string containing the valid XML for this element.
319     */
320    public java.lang.String toString(boolean includeNS, boolean declareNS) {
321        if (signed && (xmlString != null)) {
322            return xmlString;
323        }
324        
325        StringBuffer xml = new StringBuffer(3000);
326        String NS="";
327        String appendNS="";
328        if (declareNS) {
329            NS=SAMLConstants.assertionDeclareStr;
330        }
331        if (includeNS) {
332            appendNS="saml:";
333        }
334        String dateStr = null;
335        
336        if (_issueInstant != null)  {
337            dateStr = DateUtils.toUTCDateFormat(_issueInstant);
338        }
339        
340        xml.append("<").append(appendNS).append("Assertion").append(" ").
341                append(NS).append(" ").append("MajorVersion").append("=\"").
342                append(_majorVersion).append("\"").append(" ").
343                append("MinorVersion").append("=\"").append(_minorVersion).
344                append("\"").append(" ").append("AssertionID=\"").
345                append(_assertionID.getAssertionIDReference()).append("\"").
346                append(" ").append("Issuer").append("=\"").append(_issuer).
347                append("\"").append(" ").append("IssueInstant").append("=\"").
348                append(dateStr).append("\"").
349                append(" ").append(">").append(sc.NL);
350        if (_conditions != null) {
351            xml.append(_conditions.toString(includeNS, false));
352        }
353        if (_advice != null) {
354            xml.append(_advice.toString(includeNS, false));
355        }
356        Iterator i = getStatement().iterator();
357        while (i.hasNext()) {
358            Statement st = (Statement)i.next();
359            xml.append(st.toString(includeNS, declareNS));
360        }
361        if (signed && (signatureString != null)) {
362            xml.append(signatureString);
363        }
364        String o = SAMLUtils.makeEndElementTagXML("Assertion", includeNS);
365        xml.append(o);
366        return xml.toString();
367    }
368    
369    protected boolean processUnknownElement(Element element)
370    throws SAMLException {
371        if (super.processUnknownElement(element)) {
372            if (SAMLUtils.debug.messageEnabled()) {
373                SAMLUtils.debug.message(
374                        "SecurityAssertion.processUnknownElement: " +
375                        "super returns true");
376            }
377            return true;
378        }
379        
380        if (SAMLUtils.debug.messageEnabled()) {
381            SAMLUtils.debug.message(
382                    "SecurityAssertion.processUnknownElement: " +
383                    "super returns false");
384        }
385        String localName = element.getLocalName();
386        if (localName.equals("ResourceAccessStatement")) {
387            _statements.add(new ResourceAccessStatement(element));
388            return true;
389        }
390        
391        if (localName.equals("SessionContextStatement")) {
392            _statements.add(new SessionContextStatement(element));
393            return true;
394        }
395        
396        return false;
397    }
398    
399    protected int getMinAssertionMinorVersion() {
400        return sc.ASSERTION_MINOR_VERSION;
401    }
402    
403    protected int getMaxAssertionMinorVersion() {
404        return sc.ASSERTION_MINOR_VERSION;
405    }
406    
407    /**
408     * Add the <code>Assertion</code> to the Document Element.
409     *
410     * @param headerE the element to be updated.
411     * @throws Exception if there is an error.
412     */
413    public void addToParent(Element headerE) throws Exception {
414        
415        Document doc = headerE.getOwnerDocument();
416        
417        Element securityE =
418                doc.createElementNS(WSSEConstants.NS_WSSE_WSF11,
419                WSSEConstants.TAG_WSSE + ":" +
420                WSSEConstants.TAG_SECURITYT);
421        
422        securityE.setAttributeNS(SOAPBindingConstants.NS_XML,
423                WSSEConstants.TAG_XML_WSSE,
424                WSSEConstants.NS_WSSE_WSF11);
425        
426        headerE.appendChild(securityE);
427        
428        Document assertionDoc = XMLUtils.toDOMDocument(
429                toString(true, true), SAMLUtils.debug);
430        
431        Element assertionE = assertionDoc.getDocumentElement();
432        securityE.appendChild(doc.importNode(assertionE, true));
433        
434    }
435}




























































Copyright © 2010-2017, ForgeRock All Rights Reserved.