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: FSAuthnRequestEnvelope.java,v 1.2 2008/06/25 05:46:43 qcheng Exp $
026 *
027 */
028
029package com.sun.identity.federation.message;
030
031import com.sun.identity.federation.common.IFSConstants;
032import com.sun.identity.federation.message.common.FSMsgException;
033import com.sun.identity.federation.common.FSUtils;
034import com.sun.identity.saml.common.SAMLUtils;
035import com.sun.identity.shared.encode.Base64;
036import com.sun.identity.shared.xml.XMLUtils;
037import java.io.IOException;
038import java.util.List;
039import org.w3c.dom.Element;
040import org.w3c.dom.Node;
041import org.w3c.dom.NodeList;
042import org.w3c.dom.Document;
043
044/**
045 * This  class defines methods for setting and retrieving attributes and
046 * elements associated with a Liberty Authentication Request.
047 *
048 * @supported.all.api
049 */
050public class FSAuthnRequestEnvelope {
051    private String assertionConsumerServiceURL = null;
052    private List otherElements = null;
053    private FSAuthnRequest authnRequest = null;
054    private FSIDPList idpList = null;
055    private String providerID = null;
056    private String providerName = null;
057    private boolean isPassive = false;
058    private int minorVersion = IFSConstants.FF_11_PROTOCOL_MINOR_VERSION;
059    
060    /**
061     * Default Constructor.
062     */
063    public FSAuthnRequestEnvelope() {
064    }
065    
066    /**
067     * Constructs a new <code>FSAuthnRequestEnvelope</code> object.
068     *
069     * @param authnRequest the authentication request
070     * @param providerID the provider's identifier
071     * @param providerName name of the provider
072     * @param assertionConsumerServiceURL absolute url of the assertion
073     * consumer service
074     * @param idpList list of identity providers
075     * @param isPassive true if identity provider must not interact
076     *        with the <code>Principal</code>.
077     */
078    
079    public FSAuthnRequestEnvelope(FSAuthnRequest authnRequest,
080            String providerID,
081            String providerName,
082            String assertionConsumerServiceURL,
083            FSIDPList idpList, boolean isPassive ) {
084        this.authnRequest = authnRequest;
085        this.providerID = providerID;
086        this.providerName = providerName;
087        this.assertionConsumerServiceURL = assertionConsumerServiceURL;
088        this.idpList = idpList;
089        this.isPassive = isPassive;
090    }
091    
092    /**
093     * Constructs a new <code>FSAuthnRequestEnvelope</code> object
094     * from a Document Element.
095     *
096     * @param root the Document Element .
097     * @throws FSMsgException if there is an error
098     *         creating this object.
099     */
100    
101    public FSAuthnRequestEnvelope(Element root) throws FSMsgException {
102        if (root == null) {
103            SAMLUtils.debug.message(
104                    "FSAuthnRequestEnvelope.parseXML: null input.");
105            throw new FSMsgException("nullInput",null);
106        }
107        String tag = null;
108        if (((tag = root.getLocalName()) == null) ||
109                (!tag.equals(IFSConstants.AUTHN_REQUEST_ENVELOPE))) {
110            FSUtils.debug.message(
111                    "FSAuthnRequestEnvelope.parseXML: wrong input.");
112            throw new FSMsgException("wrongInput",null);
113        }
114        String ns = root.getNamespaceURI();
115        if (ns == null) {
116            FSUtils.debug.error("FSAuthnRequestEnvelope(Element):"
117                    + " No namespace");
118            throw new FSMsgException("wrongInput", null);
119        }
120        
121        if (ns.equals(IFSConstants.FF_12_XML_NS)) {
122            minorVersion = IFSConstants.FF_12_PROTOCOL_MINOR_VERSION;
123        }
124        
125        NodeList nl = root.getChildNodes();
126        Node child;
127        String childName;
128        int length = nl.getLength();
129        for (int i = 0; i < length; i++) {
130            child = nl.item(i);
131            if ((childName = child.getLocalName()) != null) {
132                if (childName.equals(
133                        IFSConstants.ASSERTION_CONSUMER_SERVICE_URL)) {
134                    assertionConsumerServiceURL =
135                            XMLUtils.getElementValue((Element) child);
136                } else if (childName.equals(IFSConstants.IDP_LIST)) {
137                    idpList = new FSIDPList((Element) child);
138                } else if (childName.equals(IFSConstants.AUTHN_REQUEST)) {
139                    authnRequest = new FSAuthnRequest((Element) child);
140                } else if (childName.equals(IFSConstants.PROVIDER_ID)) {
141                    providerID = XMLUtils.getElementValue((Element) child);
142                } else if (childName.equals(IFSConstants.PROVIDER_NAME)) {
143                    providerName = XMLUtils.getElementValue((Element) child);
144                } else if (childName.equals(IFSConstants.IS_PASSIVE)) {
145                    String strIsPassive =
146                            XMLUtils.getElementValue((Element) child);
147                    boolean isPassive = false;
148                    if (strIsPassive != null &&
149                            strIsPassive.equals(IFSConstants.TRUE)) {
150                        isPassive = true;
151                    }
152                }
153            }
154        }
155    }
156    
157    /**
158     * Returns the value of <code>MinorVersion</code> property.
159     *
160     * @return the  value of <code>MinorVersion</code> property.
161     */
162    public int getMinorVersion() {
163        return minorVersion;
164    }
165    
166    /**
167     * Sets the value of <code>MinorVersion</code> property.
168     *
169     * @param minorVersion the value of <code>MinorVersion</code> property.
170     * @see #setMinorVersion(int)
171     */
172    
173    public void setMinorVersion(int minorVersion) {
174        this.minorVersion = minorVersion;
175    }
176    
177    /**
178     * Returns the request as an XML Document String
179     * based on the Liberty Request schema.
180     *
181     * @return XML String representing the request.
182     * @throws <code>FSMsgException</code> if there is an error.
183     */
184    
185    public String toXMLString() throws FSMsgException {
186        return toXMLString(true, true);
187    }
188    
189    /**
190     * Creates a String representation of the &lt;lib:AuthnRequest&gt; element.
191     * @param includeNS : Determines whether or not the namespace qualifier
192     *        is prepended to the Element when converted
193     * @param declareNS : Determines whether or not the namespace is declared
194     *        within the Element.
195     * @return String containing the valid XML for this element.
196     * @throws FSMsgException if there is an error.
197     */
198    
199    public String toXMLString(boolean includeNS,boolean declareNS)
200    throws FSMsgException {
201        return toXMLString(includeNS, declareNS, false);
202    }
203    
204    /**
205     * Creates a String representation of the &lt;lib:AuthnRequest&gt; element.
206     *
207     * @param includeNS  Determines whether or not the namespace qualifier
208     *        is prepended to the Element when converted
209     * @param declareNS  Determines whether or not the namespace is declared
210     *        within the Element.
211     * @param includeHeader Determines whether the output include the xml
212     *        declaration header.
213     * @return A string containing the valid XML for this element.
214     * @throws <code>FSMsgException</code> if there is an error.
215     */
216    public String toXMLString(boolean includeNS,
217            boolean declareNS,
218            boolean includeHeader) throws FSMsgException {
219        
220        StringBuffer xml = new StringBuffer(300);
221        if (includeHeader) {
222            xml.append(IFSConstants.XML_PREFIX)
223            .append(IFSConstants.DEFAULT_ENCODING)
224            .append(IFSConstants.QUOTE)
225            .append(IFSConstants.SPACE)
226            .append(IFSConstants.QUESTION_MARK)
227            .append(IFSConstants.RIGHT_ANGLE)
228            .append(IFSConstants.NL);
229        }
230        String prefix = "";
231        String uri = "";
232        if (includeNS) {
233            prefix = IFSConstants.LIB_PREFIX;
234        }
235        if (declareNS) {
236            if(minorVersion == IFSConstants.FF_12_PROTOCOL_MINOR_VERSION) {
237                uri = IFSConstants.LIB_12_NAMESPACE_STRING;
238            } else {
239                uri = IFSConstants.LIB_NAMESPACE_STRING;
240            }
241        }
242        
243        xml.append(IFSConstants.LEFT_ANGLE)
244        .append(prefix)
245        .append(IFSConstants.AUTHN_REQUEST_ENVELOPE)
246        .append(uri)
247        .append(IFSConstants.RIGHT_ANGLE);
248        
249        if (authnRequest != null){
250            xml.append(authnRequest.toXMLString());
251        }
252        
253        if (providerID != null && providerID.length() != 0){
254            xml.append(IFSConstants.LEFT_ANGLE)
255            .append(prefix)
256            .append(IFSConstants.PROVIDER_ID)
257            .append(uri)
258            .append(IFSConstants.RIGHT_ANGLE)
259            .append(providerID)
260            .append(IFSConstants.START_END_ELEMENT)
261            .append(prefix)
262            .append(IFSConstants.PROVIDER_ID)
263            .append(IFSConstants.RIGHT_ANGLE);
264        }
265        
266        if (providerName != null && providerName.length() != 0){
267            xml.append(IFSConstants.LEFT_ANGLE)
268            .append(prefix)
269            .append(IFSConstants.PROVIDER_NAME)
270            .append(uri)
271            .append(IFSConstants.RIGHT_ANGLE)
272            .append(providerName)
273            .append(IFSConstants.START_END_ELEMENT)
274            .append(prefix)
275            .append("ProviderName")
276            .append(IFSConstants.PROVIDER_NAME)
277            .append(IFSConstants.RIGHT_ANGLE);
278        }
279        
280        if (assertionConsumerServiceURL != null &&
281                assertionConsumerServiceURL.length() != 0) {
282            xml.append(IFSConstants.LEFT_ANGLE)
283            .append(prefix)
284            .append(IFSConstants.ASSERTION_CONSUMER_SERVICE_URL)
285            .append(uri)
286            .append(IFSConstants.RIGHT_ANGLE)
287            .append(assertionConsumerServiceURL)
288            .append(IFSConstants.START_END_ELEMENT)
289            .append(prefix)
290            .append(IFSConstants.ASSERTION_CONSUMER_SERVICE_URL)
291            .append(IFSConstants.RIGHT_ANGLE);
292        }
293        
294        if (idpList != null){
295            xml.append(idpList.toXMLString());
296        }
297        
298        String strIsPassive = IFSConstants.FALSE;
299        if (isPassive) {
300            strIsPassive = IFSConstants.TRUE;
301        }
302        
303        xml.append(IFSConstants.LEFT_ANGLE)
304        .append(prefix)
305        .append(IFSConstants.IS_PASSIVE)
306        .append(IFSConstants.RIGHT_ANGLE)
307        .append(strIsPassive)
308        .append(IFSConstants.START_END_ELEMENT)
309        .append(prefix)
310        .append(IFSConstants.IS_PASSIVE)
311        .append(IFSConstants.RIGHT_ANGLE);
312        
313        //Other elements needs to be handled here
314        
315        xml.append(IFSConstants.START_END_ELEMENT)
316        .append(prefix)
317        .append(IFSConstants.AUTHN_REQUEST_ENVELOPE)
318        .append(IFSConstants.RIGHT_ANGLE);
319        
320        return xml.toString();
321    }
322    
323    /**
324     * Returns the <code>FSAuthnRequestEnvelope</code> object.
325     *
326     * @param xml the XML string to create this object from
327     * @return <code>FSAuthnRequestEnvelope</code> object.
328     * @throws FSMsgException if there is
329     *         error creating the object.
330     */
331    
332    public static FSAuthnRequestEnvelope parseXML(String xml)
333    throws FSMsgException {
334        Document doc = XMLUtils.toDOMDocument(xml, FSUtils.debug);
335        if (doc == null) {
336            if (FSUtils.debug.messageEnabled()) {
337                FSUtils.debug.message(
338                        "FSAuthnRequestEnvelope.parseXML:Error "
339                        + "while parsing input xml string");
340            }
341            throw new FSMsgException("parseError",null);
342        }
343        Element root = doc.getDocumentElement();
344        return new FSAuthnRequestEnvelope(root);
345    }
346    
347    /**
348     * Returns the value of <code>AssertionConsumerServiceURL</code> attribute.
349     *
350     * @return the value of <code>AssertionConsumerServiceURL</code> attribute.
351     * @see #setAssertionConsumerServiceURL(String)
352     */
353    public String getAssertionConsumerServiceURL() {
354        return assertionConsumerServiceURL;
355    }
356    
357    /**
358     * Sets the value of <code>AssertionConsumerServiceURL</code> attribute.
359     *
360     * @param assertionConsumerURL the value of
361     *        <code>AssertionConsumerServiceURL</code> attribute.
362     * @see #getAssertionConsumerServiceURL
363     */
364    
365    public void setAssertionConsumerServiceURL(String assertionConsumerURL) {
366        this.assertionConsumerServiceURL = assertionConsumerURL;
367    }
368    
369    /**
370     * Returns the <code>FSAuthnRequest</code> object.
371     *
372     * @return the <code>FSAuthnRequest</code> object.
373     * @see #setAuthnRequest(FSAuthnRequest)
374     */
375    public FSAuthnRequest getAuthnRequest() {
376        return authnRequest;
377    }
378    
379    /**
380     * Sets the <code>FSAuthnRequest</code> object.
381     *
382     * @param authnRequest the <code>FSAuthnRequest</code> object.
383     * @see #getAuthnRequest
384     */
385    public void setAuthnRequest(FSAuthnRequest authnRequest) {
386        this.authnRequest = authnRequest;
387    }
388    
389    /**
390     * Returns the <code>FSIDPList</code> object.
391     *
392     * return the <code>FSIDPList</code> object.
393     * @see #setIDPList(FSIDPList)
394     */
395    public FSIDPList getIDPList() {
396        return idpList;
397    }
398    
399    /**
400     * Sets the <code>FSIDPList</code> object.
401     *
402     * @param idpList the <code>FSIDPList</code> object.
403     * @see #getIDPList
404     */
405    public void setIDPList(FSIDPList idpList) {
406        this.idpList = idpList;
407    }
408    
409    /**
410     * Returns a list of elements.
411     *
412     * @return list of elements.
413     * @see #setOtherElements(List)
414     */
415    public List getOtherElements() {
416        return otherElements;
417    }
418    
419    /**
420     * Sets a list of elements.
421     *
422     * @param otherElements a list of elements.
423     * @see #getOtherElements
424     */
425    public void setOtherElements(List otherElements) {
426        this.otherElements = otherElements;
427    }
428    
429    /**
430     * Returns <code>FSAuthnRequestEnvelope</code> object. The object
431     * is created by parsing an Base64 encode authentication
432     * request String.
433     *
434     * @param encodedReq the encoded string.
435     * @throws <code>FSMsgException</code> if there is an error
436     *         creating <code>FSAuthnRequestEnvelope</code> object.
437     */
438    
439    public static FSAuthnRequestEnvelope parseBASE64EncodedString(
440            String encodedReq) throws FSMsgException {
441        if (encodedReq != null) {
442            String decodedAuthnReq = new String(Base64.decode(encodedReq));
443            if (FSUtils.debug.messageEnabled()) {
444                FSUtils.debug.message("FSAuthnRequestEnvelope."
445                        + "parseBASE64EncodedString: decoded input string: \n"
446                        + decodedAuthnReq);
447            }
448            return parseXML(decodedAuthnReq);
449        } else {
450            if (FSUtils.debug.messageEnabled()) {
451                FSUtils.debug.message(
452                        "FSAuthnRequestEnvelope.parseBASE64EncodedString: null "
453                        + " String passed in as argument.");
454            }
455            throw new FSMsgException("nullInput",null);
456        }
457    }
458    
459    /**
460     * Returns a Base64 Encoded Authentication Request String.
461     *
462     * @return a Base64 Encoded Authentication Request String.
463     * @throws FSMsgException if there is an error encoding
464     *         the string.
465     */
466    public String toBASE64EncodedString() throws FSMsgException {
467        if((assertionConsumerServiceURL == null) ||
468                (assertionConsumerServiceURL.length() == 0)) {
469            FSUtils.debug.error("FSAuthnRequestEnvelope.toBASE64EncodedString:"
470                    + "assertionConsumerServiceURL is null in the "
471                    + "FSAuthnRequestEnvelope");
472            throw new FSMsgException(
473                    "noAssertionConsumerServiceURLElement",null);
474        }
475        if (authnRequest == null){
476            FSUtils.debug.error("FSAuthnRequestEnvelope.toBASE64EncodedString:"
477                    + "authnRequest is null in the FSAuthnRequestEnvelope");
478            throw new FSMsgException("noAuthnRequestElement",null);
479        }
480        return Base64.encode(this.toXMLString().getBytes());
481    }
482}