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: SubjectConfirmation.java,v 1.2 2008/06/25 05:47:33 qcheng Exp $
026 *
027 */
028  
029package com.sun.identity.saml.assertion;
030
031import com.sun.identity.saml.common.SAMLException;
032import com.sun.identity.saml.common.SAMLUtilsCommon;
033import com.sun.identity.saml.common.SAMLRequesterException;
034import com.sun.identity.saml.common.SAMLConstants;
035import com.sun.identity.shared.xml.XMLUtils;
036import org.w3c.dom.Element;
037import org.w3c.dom.Node;
038import org.w3c.dom.NodeList;
039import java.util.Set;
040import java.util.Iterator;
041import java.util.Collections;
042import java.util.HashSet;
043
044/**
045 *The <code>SubjectConfirmation</code> element specifies a subject by specifying
046 *data that authenticates the subject. 
047 *@supported.all.api
048 */
049public class SubjectConfirmation {
050    static SAMLConstants sc;
051    private Set _confirmationMethodList = 
052        Collections.synchronizedSet(new HashSet());
053    private Element  _subjectConfirmationData=null;
054    private Element _keyInfo=null; 
055   
056    /** 
057     * Constructs a subject confirmation element from an existing 
058     * XML block.
059     *
060     * @param subjectConfirmationElement a DOM Element representing the 
061     *        <code>SubjectConfirmation</code> object. 
062     * @throws SAMLException
063     */
064    public SubjectConfirmation(org.w3c.dom.Element subjectConfirmationElement) 
065        throws SAMLException 
066    {
067        Element elt = (Element) subjectConfirmationElement;
068        String eltName = elt.getLocalName();
069        if (eltName == null)  {
070            if (SAMLUtilsCommon.debug.messageEnabled()) {
071                SAMLUtilsCommon.debug.message("SubjectConfirmation: local name "
072                        + "missing");
073            }
074            throw new SAMLRequesterException(SAMLUtilsCommon.bundle.getString
075                ("nullInput")) ;   
076        }
077        if (!(eltName.equals("SubjectConfirmation")))  {
078            if (SAMLUtilsCommon.debug.messageEnabled()) {
079                SAMLUtilsCommon.debug.message("SubjectConfirmation: "+
080                    "invalid root element");
081            }
082            throw new SAMLRequesterException(SAMLUtilsCommon.bundle.getString(
083                "invalidElement")) ;   
084        }
085        // TODO: Not checking for the sequence of elements
086        NodeList nl = elt.getChildNodes();
087        int length = nl.getLength();
088        for (int n=0; n<length; n++) {
089            Node child = (Node)nl.item(n);
090            if (child.getNodeType() != Node.ELEMENT_NODE) {
091                continue;
092            }
093            String childName = child.getLocalName();
094            if (childName.equals("ConfirmationMethod")) {
095                _confirmationMethodList.add(
096                    XMLUtils.getElementValue((Element) child));
097            }
098            else if (childName.equals("SubjectConfirmationData")) {
099                if (_subjectConfirmationData != null) {
100                // this is the seconf time this is passed so flag error
101                    if (SAMLUtilsCommon.debug.messageEnabled()) {
102                        SAMLUtilsCommon.debug.message("SubjectConfirmation: "
103                            + "SubjectConfirmationData already parsed");
104                    }
105                    throw new SAMLRequesterException(
106                        SAMLUtilsCommon.bundle.getString("moreElement"));
107                }
108                _subjectConfirmationData = (Element) child;
109            }
110            else if (childName.equals("KeyInfo")) {
111                if (_keyInfo != null) {
112                    if (SAMLUtilsCommon.debug.messageEnabled()) {
113                        SAMLUtilsCommon.debug.message("SubjectConfirmation: "
114                            + "KeyInfo already parsed");
115                    }
116                    throw new SAMLRequesterException(
117                        SAMLUtilsCommon.bundle.getString("moreElement"));
118                }
119                _keyInfo = (Element) child;
120            } else {
121                if (SAMLUtilsCommon.debug.messageEnabled()) 
122                    SAMLUtilsCommon.debug.message("SubjectConfirmation: " + 
123                        "unsupported element KeyInfo in SubjectConfirmation");
124                throw new SAMLRequesterException(
125                    SAMLUtilsCommon.bundle.getString("unsupportedElement"));
126            }
127        }       
128
129        if (_confirmationMethodList.isEmpty()) {
130            if (SAMLUtilsCommon.debug.messageEnabled()) 
131                SAMLUtilsCommon.debug.message("SubjectConfirmation: Mandatory "
132                    + "element confirmation method missing");
133            throw new SAMLRequesterException(SAMLUtilsCommon.bundle.getString(
134                "missingElement"));
135        }
136    }
137          
138    /**  
139     * Constructor with a single confirmation method.
140     *
141     * @param confirmationMethod A URI (String) that identifies a protocol used
142     *        to authenticate a <code>Subject</code>. Please refer to
143     *        <code>draft-sstc-core-25</code> Section 7 for a list of URIs
144     *        identifying common authentication protocols.
145     * @exception SAMLException if the input data is null.
146     */
147    public SubjectConfirmation(java.lang.String confirmationMethod) 
148        throws SAMLException 
149    {
150        if ((confirmationMethod == null) ||
151            (confirmationMethod.length() == 0)) {
152            if (SAMLUtilsCommon.debug.messageEnabled()) {
153                SAMLUtilsCommon.debug.message("SubjectConfirmation:  null "
154                    + "confirmationMethod specified");
155            }
156            throw new SAMLRequesterException(SAMLUtilsCommon.bundle.getString(
157                "nullInput")) ;   
158        }
159        _confirmationMethodList.add(confirmationMethod);
160    }
161     
162    /** 
163     * Constructor for multiple confirmation methods
164     * @param confirmationMethods a <code>Set</code> of
165     *        <code>confirmationMethods</code>
166     * @exception SAMLException if the <code>confirmationMethods</code> is
167     *            empty.
168     */    
169    public SubjectConfirmation(Set confirmationMethods) throws SAMLException {
170        if (confirmationMethods.isEmpty()) {
171            if (SAMLUtilsCommon.debug.messageEnabled()) {
172                SAMLUtilsCommon.debug.message("SubjectConfirmation:  No "
173                    + "confirmationMethods  in the Set");
174            }
175            throw new SAMLRequesterException(SAMLUtilsCommon.bundle.getString(
176                "nullInput")) ;   
177        }
178        _confirmationMethodList.addAll(confirmationMethods);
179    }
180
181    /** 
182     * Adds a <code>confirmationMethod</code> to this
183     * <code>SubjectConfirmation</code> element.
184     *
185     * @param confirmationMethod a String which is a URI (String) that 
186     *        identifies a protocol used to authenticate a <code>Subject</code>.
187     * @return true indicating success of the operation.
188     */    
189    public boolean addConfirmationMethod(String confirmationMethod) {
190        if ((confirmationMethod == null) ||
191            (confirmationMethod.length() == 0)) {
192            return false;
193        }
194        _confirmationMethodList.add(confirmationMethod);
195        return true;
196    }
197          
198    /**
199     * Constructs an <code>SubjectConfirmation</code> instance.
200     *
201     * @param confirmationMethods A set of <code>confirmationMethods</code>
202     *        each of which is a URI (String) that identifies a protocol
203     *        used to authenticate a <code>Subject</code>. Please refer to
204     *        <code>draft-sstc-core-25</code> Section 7 for 
205     *        a list of URIs identifying common authentication protocols.
206     * @param subjectConfirmationData Additional authentication information to 
207     *        be used by a specific authentication protocol. Can be passed as
208     *        null if there is no <code>subjectConfirmationData</code> for the
209     *        <code>SubjectConfirmation</code> object.
210     * @param keyInfo An XML signature element that specifies a cryptographic 
211     *        key held by the <code>Subject</code>. 
212     * @exception SAMLException if the input data is invalid or 
213     *            <code>confirmationMethods</code> is empty.
214     */
215    public SubjectConfirmation(Set confirmationMethods, 
216                               Element subjectConfirmationData,
217                               Element keyInfo) throws SAMLException
218    {
219        if (confirmationMethods.isEmpty()) {
220            if (SAMLUtilsCommon.debug.messageEnabled()) {
221                SAMLUtilsCommon.debug.message("SubjectConfirmation:  No "
222                    + "confirmationMethods  in the Set");
223            }
224            throw new SAMLRequesterException(SAMLUtilsCommon.bundle.getString(
225                "nullInput")) ;   
226        }
227        _confirmationMethodList.addAll(confirmationMethods);
228        _subjectConfirmationData = subjectConfirmationData;   
229        _keyInfo = keyInfo;   
230    }
231   
232    /**
233     *Gets Confirmation Method(s)
234     *@return A <code>java.util.Set</code> of confirmation Methods. Each method 
235     *contained within is a <code>String</code> representing the confirmation 
236     * method.
237     */
238    public Set  getConfirmationMethod() {
239        return _confirmationMethodList;
240    }
241   
242    /**
243     *Get Subject Confirmation Data
244     *@return A String representation of the subject confirmation data with the 
245     *Subject Confirmation element 
246     */
247    public Element getSubjectConfirmationData() {
248        return _subjectConfirmationData;
249    }
250   
251    /**
252     * Sets the <code>SubjectConfirmationData</code>
253     *
254     * @param subjectConfirmationData A String representation of the subject 
255     *        confirmation data within this <code>SubjectConfirmation</code>
256     *        element 
257     * @return true indicating success of the operation.
258     */
259    public boolean setSubjectConfirmationData(
260        Element subjectConfirmationData) 
261    {
262        if (subjectConfirmationData == null) {
263            return false;
264        }
265        _subjectConfirmationData = subjectConfirmationData;
266        return true;
267    }
268
269    /**
270     * Sets the <code>SubjectConfirmationData</code>.
271     *
272     * @param scDataString A String representation of the subject 
273     *        confirmation data within this <code>SubjectConfirmation</code>
274     *        element.
275     * @return true if the operation succeed.
276     */
277    public boolean setSubjectConfirmationData(String scDataString) {
278        if (scDataString == null) {
279            return false;
280        }
281        StringBuffer sb = new StringBuffer(300);
282        sb.append(SAMLUtilsCommon.makeStartElementTagXML(
283                "SubjectConfirmationData", true, true)).
284                append(scDataString).
285                append(SAMLUtilsCommon.makeEndElementTagXML(
286                        "SubjectConfirmationData", true));
287        try {
288            _subjectConfirmationData = XMLUtils.toDOMDocument(
289                        sb.toString().trim(),
290                        SAMLUtilsCommon.debug).getDocumentElement();
291        } catch (Exception e) {
292            if (SAMLUtilsCommon.debug.messageEnabled()) {
293                SAMLUtilsCommon.debug.message("SubjectConfirmation: " +
294                    "exception when setting scDataString.", e);
295            }
296            return false;
297        }
298        return true;
299    }
300
301    /**
302     * Returns the key info.
303     *
304     * @return The key info.
305    */
306    public Element getKeyInfo() {
307        return _keyInfo;
308    }
309   
310    /**
311     * Sets the key info.
312     *
313     * @param keyInfo <code>dsig.KeyInfo</code>.
314     * @return true if operations succeeds.
315     */
316    public boolean setKeyInfo(Element keyInfo) {
317        if (keyInfo != null) {
318            _keyInfo = keyInfo;
319            return true;
320        } else {
321            return false;
322        }
323    }
324   
325    /**
326     * Checks for equality between this object and the
327     * <code>SubjectConfirmation</code> passed down as parameter. Checks to
328     * see that each have confirmations method present in the other one (does
329     * not care about sequence)
330     * Also does an exact match on <code>SubjectConfirmationData</code>.
331     * Note: no check is done for <code>KeyInfo</code>.
332     *
333     * @param subjectConfirmation <code>SubjectConfirmation</code> to be
334     *        checked.
335     * @return true if the two are EXACTLY equal.
336     */
337    public boolean equals(SubjectConfirmation subjectConfirmation) {
338        boolean cmEqual = true;
339        boolean scDataEqual = true;
340        if (subjectConfirmation != null) {
341            Set confMethods = subjectConfirmation.getConfirmationMethod();
342            int passedSize = confMethods.size();
343            if (passedSize != _confirmationMethodList.size()) {
344                cmEqual =  false;
345            } else {
346                Iterator it = confMethods.iterator();
347                while (it.hasNext()) {
348                    String confMethodStr = (String)it.next();
349                    if(!_confirmationMethodList.contains(confMethodStr)) {
350                        cmEqual=  false;
351                        break;
352                    }
353                }
354            }
355            // came here hence confirmations methods are equal
356            Element scData = subjectConfirmation.getSubjectConfirmationData();
357            if (_subjectConfirmationData != null) {
358                if (scData == null) {
359                    scDataEqual = false;
360                } else {
361                    String thisString = printSCData(_subjectConfirmationData,
362                                                        true, true);
363                    String passString = printSCData(scData, true, true);
364                    scDataEqual = thisString.equals(passString);
365                }
366            } else if (scData != null) {
367                scDataEqual= false; // one is null not the other
368            }
369            if (!(cmEqual) || !(scDataEqual)) {
370                return false;
371            }
372        } else {
373            return false; // this object atleast has mandatory confirmation 
374                          // method, while passed one is null hence false
375        }
376        return true; // if got here, then they are equal
377    }
378
379    private String printSCData(Element scData,
380                                boolean includeNS,
381                                boolean declareNS)
382    {
383        StringBuffer xml = new StringBuffer(1000);
384        xml.append(SAMLUtilsCommon.makeStartElementTagXML(
385                "SubjectConfirmationData", includeNS, declareNS));
386        NodeList nl = scData.getChildNodes();
387        for (int i = 0, len = nl.getLength(); i < len; i++) {
388            xml.append(XMLUtils.print(nl.item(i)));
389        }
390        xml.append(SAMLUtilsCommon.makeEndElementTagXML(
391                "SubjectConfirmationData", includeNS));
392        return xml.toString();
393    }
394
395    /**
396     * Returns a String representation of the  element
397     *
398     * @return A string containing the valid XML for this element
399     *         By default name space name is prepended to the element name 
400     *         example <code>&lt;saml:SubjectConfirmation&gt;</code>.
401     */
402    public java.lang.String toString() {
403        // call toString() with includeNS true by default and declareNS false
404        String xml = this.toString(true, false);
405        return xml;
406    }
407
408    /**
409     * Returns a String representation of the
410     * <code>&lt;SubjectConfirmation&gt;</code> element.
411     *
412     * @param includeNS Determines whether or not the namespace qualifier is
413     *        prepended to the Element when converted
414     * @param declareNS Determines whether or not the namespace is declared
415     *        within the Element.
416     * @return A string containing the valid XML for this element.
417    */ 
418    public java.lang.String  toString(boolean includeNS, boolean declareNS) {
419        StringBuffer xml = new StringBuffer(3000);
420        String o = SAMLUtilsCommon.makeStartElementTagXML(
421                  "SubjectConfirmation", includeNS, declareNS);
422        xml.append(o).append(sc.NL);
423        if (_confirmationMethodList.size() > 0 ) {
424            Iterator it = _confirmationMethodList.iterator();
425            while (it.hasNext()) {
426                o = SAMLUtilsCommon.makeStartElementTagXML(
427                    "ConfirmationMethod",includeNS, false);
428                xml.append(o).append((String)it.next());
429                o = SAMLUtilsCommon.makeEndElementTagXML(
430                    "ConfirmationMethod",includeNS);
431                xml.append(o);
432            }
433        }
434        
435        if (_subjectConfirmationData != null)  {
436            xml.append(
437                printSCData(_subjectConfirmationData, includeNS, false));
438        }
439        if (_keyInfo != null) {
440            xml.append(XMLUtils.print(_keyInfo));
441        }
442        o = SAMLUtilsCommon.makeEndElementTagXML("SubjectConfirmation",
443                                                 includeNS);
444        xml.append(o);
445        return xml.toString();
446    }                           
447}




























































Copyright © 2010-2017, ForgeRock All Rights Reserved.