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: FSLogoutResponse.java,v 1.4 2008/06/25 05:46:44 qcheng Exp $
026 * Portions Copyrighted 2014 ForgeRock AS
027 */
028
029package com.sun.identity.federation.message;
030
031import com.sun.identity.shared.encode.Base64;
032import com.sun.identity.shared.encode.URLEncDec;
033import com.sun.identity.shared.xml.XMLUtils;
034
035import com.sun.identity.shared.DateUtils;
036
037import com.sun.identity.federation.message.common.FSMsgException;
038import com.sun.identity.federation.common.FSUtils;
039import com.sun.identity.federation.common.IFSConstants;
040
041import com.sun.identity.saml.common.SAMLConstants;
042import com.sun.identity.saml.common.SAMLException;
043import com.sun.identity.saml.common.SAMLResponderException;
044import com.sun.identity.saml.common.SAMLVersionMismatchException;
045
046import com.sun.identity.saml.xmlsig.XMLSignatureManager;
047
048import com.sun.identity.saml.protocol.AbstractResponse;
049import com.sun.identity.saml.protocol.Status;
050import com.sun.identity.saml.protocol.StatusCode;
051
052import java.io.IOException;
053
054import java.text.ParseException;
055
056import java.util.Date;
057import java.util.List;
058
059import javax.servlet.http.HttpServletRequest;
060
061import org.w3c.dom.Element;
062import org.w3c.dom.Node;
063import org.w3c.dom.NodeList;
064import org.w3c.dom.Document;
065
066/**
067 * This class has methods to create a Liberty <code>LogoutResponse</code>.
068 *
069 * @supported.all.api
070 * @deprecated since 12.0.0
071 */
072@Deprecated
073public class FSLogoutResponse extends AbstractResponse {
074    private String providerId;
075    private String relayState;
076    private Status status;
077    protected String xmlString;
078    protected String signatureString;
079    protected String id;
080    private String inResponseTo;
081    
082    /**
083     * Default Constructor.
084     */
085    public FSLogoutResponse() {
086        try {
087            setIssueInstant(new Date());
088            providerId = new String();
089            StatusCode statusCode = new StatusCode(IFSConstants.SAML_SUCCESS);
090            status = new Status(statusCode);
091            relayState = new String();
092        } catch (SAMLException e){
093            FSUtils.debug.error("FSLogoutResponse.constructor:", e);
094        }
095        
096    }
097    
098    /**
099     * Constructor creates <code>FSLogoutResponse</code> object.
100     *
101     * @param responseID the value of <code>ResponseID</code> attribute.
102     * @param inResponseTo the value of <code>inResponseTo</code> attribute.
103     * @param status the  Logout <code>Status</code>  object.
104     * @param providerId the value of <code>ProviderID</code> attribute.
105     * @param relayState the value of <code>RelayState</code> attribute.
106     * @throws <code>FSMsgException</code> if this object cannot be created.
107     */
108    public FSLogoutResponse(String responseID,
109            String inResponseTo,
110            Status status,
111            String providerId,
112            String relayState)
113            throws FSMsgException {
114        if ((responseID == null) || (responseID.length() == 0)) {
115            this.responseID = FSUtils.generateID();
116            if (this.responseID == null) {
117                throw new FSMsgException("errorGenerateID",null);
118            }
119        } else {
120            this.responseID = responseID;
121        }
122        
123        if (inResponseTo == null) {
124            FSUtils.debug.message("Response: inResponseTo is null.");
125            throw new FSMsgException("nullInput",null);
126        }
127        this.inResponseTo = inResponseTo;
128        if (status == null) {
129            FSUtils.debug.message("Response: missing <Status>.");
130            throw new FSMsgException("missingElement",null);
131        }
132        this.status = status;
133        this.providerId = providerId;
134        this.relayState = relayState;
135        setIssueInstant(new Date());
136    }
137    
138    /**
139     * Constructor creates <code>FSLogoutResponse</code> object from
140     * a Document element.
141     *
142     * @param root the Document element object.
143     * @throws FSMsgException if this object cannot be created.
144     * @throws SAMLException if there is an error.
145     */
146    public FSLogoutResponse(Element root) throws FSMsgException, SAMLException {
147        if (root == null) {
148            FSUtils.debug.message("FSLogoutResponse.parseXML: null input.");
149            throw new FSMsgException("nullInput",null);
150        }
151        String tag = null;
152        if (((tag = root.getLocalName()) == null) ||
153                (!tag.equals(IFSConstants.LOGOUT_RESPONSE))) {
154            FSUtils.debug.message("FSLogoutResponse.parseXML: wrong input.");
155            throw new FSMsgException("wrongInput",null);
156        }
157        
158        id = root.getAttribute(IFSConstants.ID);
159        
160        // Attribute ResponseID
161        responseID = root.getAttribute(IFSConstants.RESPONSE_ID);
162        if ((responseID == null) || (responseID.length() == 0)) {
163            if (FSUtils.debug.messageEnabled()) {
164                FSUtils.debug.message("FSLogoutResponse.parseXML: "
165                        + "Reponse doesn't have ResponseID.");
166            }
167            String[] args = { IFSConstants.RESPONSE_ID };
168            throw new FSMsgException("missingAttribute",args);
169        }
170        parseMajorVersion(root.getAttribute(IFSConstants.MAJOR_VERSION));
171        parseMinorVersion(root.getAttribute(IFSConstants.MINOR_VERSION));
172        // Attribute InResponseTo
173        inResponseTo = root.getAttribute(IFSConstants.IN_RESPONSE_TO);
174        if (inResponseTo == null) {
175            if (FSUtils.debug.messageEnabled()) {
176                FSUtils.debug.message("FSLogoutResponse.parseXML: "
177                        + "Response doesn't have InResponseTo.");
178            }
179            String[] args = { IFSConstants.IN_RESPONSE_TO };
180            throw new FSMsgException("missingAttribute",args);
181        }
182        // Attribute IssueInstant
183        String instantString = root.getAttribute(IFSConstants.ISSUE_INSTANT);
184        if ((instantString == null) || (instantString.length() == 0)) {
185            FSUtils.debug.message("FSLogoutResponse(Element): "
186                    + "missing IssueInstant");
187            String[] args = { IFSConstants.ISSUE_INSTANT };
188            throw new FSMsgException("missingAttribute",args);
189        } else {
190            try {
191                issueInstant = DateUtils.stringToDate(instantString);
192            } catch (ParseException e) {
193                if (FSUtils.debug.messageEnabled()) {
194                    FSUtils.debug.message(
195                            "FSLogoutResponse(Element): could not " +
196                            "parse IssueInstant", e);
197                }
198                throw new FSMsgException("wrongInput", null);
199            }
200        }
201        
202        NodeList nl = root.getChildNodes();
203        Node child;
204        String childName;
205        int length = nl.getLength();
206        for (int i = 0; i < length; i++) {
207            child = nl.item(i);
208            if ((childName = child.getLocalName()) != null) {
209                if (childName.equals(IFSConstants.STATUS)) {
210                    if (status != null) {
211                        if (FSUtils.debug.messageEnabled()) {
212                            FSUtils.debug.message(
213                                    "FSLogoutResponse: included more"
214                                    + " than one <Status>");
215                        }
216                        throw new FSMsgException("moreElement",null);
217                    }
218                    status = new Status((Element) child);
219                } else if (childName.equals(IFSConstants.SIGNATURE)) {
220                } else if (childName.equals(IFSConstants.PROVIDER_ID)) {
221                    if (providerId != null) {
222                        if (FSUtils.debug.messageEnabled()) {
223                            FSUtils.debug.message(
224                                    "FSLogoutResponse: included more"
225                                    + " than one providerId");
226                        }
227                        throw new FSMsgException("moreElement",null);
228                    }
229                    providerId = XMLUtils.getElementValue((Element) child);
230                } else if (childName.equals(IFSConstants.RELAY_STATE)) {
231                    relayState = XMLUtils.getElementValue((Element) child);
232                } else {
233                    if (FSUtils.debug.messageEnabled()) {
234                        FSUtils.debug.message("FSLogoutResponse: included wrong"
235                                + " element:" + childName);
236                    }
237                    throw new FSMsgException("wrongInput",null);
238                }
239            } // end if childName != null
240        } // end for loop
241        
242        if (status == null) {
243            FSUtils.debug.message("FSLogoutResponse:missing element <Status>.");
244            throw new FSMsgException("oneElement",null);
245        }
246        
247        if (providerId == null) {
248            FSUtils.debug.message(
249                    "FSLogoutResponse: missing element providerId.");
250            throw new FSMsgException("oneElement",null);
251        }
252        
253        //check for signature
254        List signs = XMLUtils.getElementsByTagNameNS1(root,
255                SAMLConstants.XMLSIG_NAMESPACE_URI,
256                SAMLConstants.XMLSIG_ELEMENT_NAME);
257        int signsSize = signs.size();
258        if (signsSize == 1) {
259            Element elem = (Element)signs.get(0);
260            setSignature(elem);
261            xmlString = XMLUtils.print(root);
262            signed = true;
263        } else if (signsSize != 0) {
264            if (FSUtils.debug.messageEnabled()) {
265                FSUtils.debug.message(
266                        "FSLogoutResponse(Element): included more than"
267                        + " one Signature element.");
268            }
269            throw new FSMsgException("moreElement",null);
270        }
271    }
272    
273    /**
274     * Returns the value of <code>RelayState</code> attribute.
275     *
276     * @return the value of <code>RelayState</code> attribute.
277     * @see #setRelayState(String)
278     */
279    public String getRelayState(){
280        return relayState;
281    }
282    
283    /**
284     * Set the value of <code>RelayState</code> attribute.
285     *
286     * @param relayState the value of <code>RelayState</code> attribute.
287     * @see #getRelayState()
288     */
289    public void setRelayState(String relayState){
290        this.relayState = relayState;
291    }
292    
293    /**
294     * Returns the value of <code>InResponseTo</code> attribute.
295     *
296     * @return the value of <code>InResponseTo</code> attribute.
297     * @see #setResponseTo(String)
298     */
299    public String getResponseTo(){
300        return inResponseTo;
301    }
302    
303    /**
304     * Sets the value of <code>InResponseTo</code> attribute.
305     *
306     * @param inResponseTo the value of <code>InResponseTo</code> attribute.
307     * @see #getResponseTo
308     */
309    public void setResponseTo(String inResponseTo){
310        this.inResponseTo = inResponseTo;
311    }
312    
313    /**
314     * Returns the value of <code>id</code> attribute.
315     *
316     * @return the value of <code>id</code> attribute.
317     * @see #setID(String)
318     */
319    public String getID(){
320        return id;
321    }
322    
323    /**
324     * Sets the value of <code>id</code> attribute.
325     *
326     * @param id the value of <code>id</code> attribute.
327     * @see #getID()
328     */
329    public void setID(String id){
330        this.id = id;
331    }
332    
333    /**
334     * Returns the value of <code>ProviderID</code> attribute.
335     *
336     * @return the value of <code>ProviderID</code> attribute.
337     * @see #setProviderId(String).
338     */
339    
340    public String getProviderId(){
341        return providerId;
342    }
343    
344    /**
345     * Sets the value of  <code>ProviderID</code> attribute.
346     *
347     * @param providerId the value of  <code>ProviderID</code> attribute.
348     * @see #getProviderId()
349     */
350    public void setProviderId(String providerId){
351        this.providerId = providerId;
352    }
353    
354    /**
355     * Returns the Signed <code>LogoutResponse</code> string.
356     *
357     * @return signatureString the Signed <code>LogoutResponse</code> string.
358     */
359    public String getSignatureString(){
360        return signatureString;
361    }
362    
363    /**
364     * Returns the value of <code>MinorVersion</code> attribute.
365     *
366     * @return the value of <code>MinorVersion</code> attribute.
367     * @see #setMinorVersion(int)
368     */
369    public int getMinorVersion() {
370        return minorVersion;
371    }
372    
373    /**
374     * Sets the value of <code>MinorVersion</code> attribute.
375     *
376     * @param version thevalue of <code>MinorVersion</code> attribute.
377     * @see #getMinorVersion()
378     */
379    public void setMinorVersion(int version) {
380        minorVersion = version;
381    }
382    
383    /**
384     * Returns the Logout <code>Status</code>.
385     *
386     * @return the Logout <code>Status</code>.
387     * @see #setStatus(String)
388     * @see #setStatus(Status)
389     */
390    public Status getStatus() {
391        return status;
392    }
393    
394    /**
395     * Sets the Logout <code>Status</code>.
396     *
397     * @param status the Logout <code>Status</code code.
398     * @see #getStatus
399     */
400    public void setStatus(String status) {
401        try {
402            StatusCode statusCode = new StatusCode(status);
403            this.status = new Status(statusCode);
404        } catch (Exception e) {
405            if (FSUtils.debug.messageEnabled()) {
406                FSUtils.debug.message("FSLogoutResponse(Element): could not "
407                        + "set attribute:", e);
408            }
409        }
410    }
411    
412    /**
413     * Sets the Logout <code>Status</code>.
414     *
415     * @param status the Logout <code>Status</code object.
416     * @see #getStatus
417     */
418    public void setStatus(Status status) {
419        this.status=status;
420    }
421    
422    /**
423     * Sets the <code>MajorVersion</code> by parsing the version string.
424     *
425     * @param majorVer a String representing the <code>MajorVersion</code> to
426     *        be set.
427     * @throws FSMsgException on error.
428     * @throws SAMLException when the version mismatchs.
429     */
430    private void parseMajorVersion(String majorVer)
431    throws FSMsgException, SAMLException {
432        try {
433            majorVersion = Integer.parseInt(majorVer);
434        } catch (NumberFormatException e) {
435            if (FSUtils.debug.messageEnabled()) {
436                FSUtils.debug.message("Response(Element): invalid "
437                        + "MajorVersion", e);
438            }
439            throw new FSMsgException("wrongInput",null);
440        }
441        
442        if (majorVersion != SAMLConstants.PROTOCOL_MAJOR_VERSION) {
443            if (majorVersion > SAMLConstants.PROTOCOL_MAJOR_VERSION) {
444                if (FSUtils.debug.messageEnabled()) {
445                    FSUtils.debug.message("Response(Element):MajorVersion of"
446                            + " the Response is too high.");
447                }
448                throw new SAMLVersionMismatchException(FSUtils.BUNDLE_NAME,
449                        "responseVersionTooHigh",null);
450            } else {
451                if (FSUtils.debug.messageEnabled()) {
452                    FSUtils.debug.message("Response(Element):MajorVersion of"
453                            + " the Response is too low.");
454                }
455                throw new SAMLVersionMismatchException(FSUtils.BUNDLE_NAME,
456                        "responseVersionTooLow",null);
457            }
458        }
459    }
460    
461    /**
462     * Sets the <code>MinorVersion</code> by parsing the version string.
463     *
464     * @param minorVer a String representing the <code>MinorVersion</code> to
465     *        be set.
466     * @throws SAMLException when the version mismatchs.
467     */
468    private void parseMinorVersion(String minorVer)
469    throws FSMsgException, SAMLException {
470        try {
471            minorVersion = Integer.parseInt(minorVer);
472        } catch (NumberFormatException e) {
473            if (FSUtils.debug.messageEnabled()) {
474                FSUtils.debug.message("Response(Element): invalid "
475                        + "MinorVersion", e);
476            }
477            throw new FSMsgException("wrongInput",null);
478        }
479        if (minorVersion > IFSConstants.FF_12_PROTOCOL_MINOR_VERSION) {
480            FSUtils.debug.error("Response(Element):MinorVersion of"
481                               + " the Response is too high.");
482            throw new SAMLVersionMismatchException(FSUtils.BUNDLE_NAME,
483                        "responseVersionTooHigh",null);
484        } else if (minorVersion < IFSConstants.FF_11_PROTOCOL_MINOR_VERSION) {
485            FSUtils.debug.error("Response(Element):MinorVersion of"
486                                  + " the Response is too low.");
487            throw new SAMLVersionMismatchException(FSUtils.BUNDLE_NAME,
488                        "responseVersionTooLow",null);
489        }
490    }
491    
492    /**
493     * Returns the <code>FSLogoutResponse</code> object.
494     *
495     * @param xml the XML string to be parsed.
496     * @return <code>FSLogoutResponse</code> object created from the XML string.
497     * @throws FSMsgException if there is
498     *         error creating the object.
499     */
500    
501    public static FSLogoutResponse parseXML(String xml) throws FSMsgException {
502        FSLogoutResponse logoutResponse = null;
503        try{
504            Document doc = XMLUtils.toDOMDocument(xml, FSUtils.debug);
505            Element root = doc.getDocumentElement();
506            logoutResponse = new FSLogoutResponse(root);
507        }catch(SAMLException ex){
508            if (FSUtils.debug.messageEnabled()) {
509                FSUtils.debug.message("FSLogoutResponse.parseXML: "
510                        + "Error while parsing input xml string");
511            }
512            throw new FSMsgException("parseError",null, ex);
513        }
514        return logoutResponse;
515    }
516    
517    /**
518     * Returns a String representation of the <code>LogoutResponse</code>
519     * object. This method translates the response to an XML string.
520     *
521     * @return An XML String representing the logout response.
522     */
523    public String toXMLString()  throws FSMsgException {
524        return this.toXMLString(true, true);
525    }
526    
527    /**
528     * Returns a String representation of the <code>LogoutResponse</code>
529     * object.
530     *
531     * @return An XML String representing the logout response.
532     * @throws FSMsgException if there is an error converting
533     *         this object ot a string.
534     */
535    public String toXMLString(boolean includeNS, boolean declareNS)
536    throws FSMsgException {
537        return toXMLString(includeNS, declareNS, false);
538    }
539    
540    /**
541     * Returns a String representation of the <code>LogoutResponse</code>
542     * object.
543     *
544     * @param includeNS Determines whether or not the namespace qualifier
545     *        is prepended to the Element when converted
546     * @param declareNS Determines whether or not the namespace is declared
547     *        within the Element.
548     * @param includeHeader Determines whether the output include the xml
549     *        declaration header.
550     * @return a string containing the valid XML for this element
551     * @throws FSMsgException if there is an error converting
552     *         this object ot a string.
553     */
554    
555    public String toXMLString(boolean includeNS, boolean declareNS,
556            boolean includeHeader)  throws FSMsgException {
557        StringBuffer xml = new StringBuffer(300);
558        if (includeHeader) {
559            xml.append(IFSConstants.XML_PREFIX)
560            .append(SAMLConstants.DEFAULT_ENCODING)
561            .append(IFSConstants.QUOTE)
562            .append(IFSConstants.SPACE)
563            .append(IFSConstants.QUESTION_MARK)
564            .append(IFSConstants.RIGHT_ANGLE)
565            .append(IFSConstants.NL);
566        }
567        String prefixLIB = "";
568        String uriLIB = "";
569        if (includeNS) {
570            prefixLIB = IFSConstants.LIB_PREFIX;
571        }
572        
573        if (declareNS) {
574            if(minorVersion == IFSConstants.FF_12_PROTOCOL_MINOR_VERSION) {
575                uriLIB = IFSConstants.LIB_12_NAMESPACE_STRING;
576            } else {
577                uriLIB = IFSConstants.LIB_NAMESPACE_STRING;
578            }
579        }
580        
581        String instantString = DateUtils.toUTCDateFormat(issueInstant);
582        
583        if((providerId == null) || (providerId.length() == 0)){
584            FSUtils.debug.error("FSLogoutResponse.toXMLString: "
585                    + "providerId is null in the response with responseId:"
586                    + responseID);
587            String[] args = { responseID };
588            throw new FSMsgException("nullProviderIdWResponseId",args);
589        }
590        
591        xml.append(IFSConstants.LEFT_ANGLE)
592        .append(prefixLIB)
593        .append(IFSConstants.LOGOUT_RESPONSE)
594        .append(uriLIB)
595        .append(IFSConstants.SPACE);
596        
597        if (minorVersion == IFSConstants.FF_11_PROTOCOL_MINOR_VERSION &&
598                id != null && !(id.length() == 0)) {
599            xml.append(IFSConstants.ID)
600            .append(IFSConstants.EQUAL_TO)
601            .append(IFSConstants.QUOTE)
602            .append(id)
603            .append(IFSConstants.QUOTE)
604            .append(IFSConstants.SPACE)
605            .append(IFSConstants.SPACE);
606        }
607        
608        if (responseID != null) {
609            xml.append(IFSConstants.RESPONSE_ID)
610            .append(IFSConstants.EQUAL_TO)
611            .append(IFSConstants.QUOTE)
612            .append(responseID)
613            .append(IFSConstants.QUOTE)
614            .append(IFSConstants.SPACE)
615            .append(IFSConstants.SPACE);
616        }
617        
618        if (inResponseTo != null) {
619            xml.append(IFSConstants.IN_RESPONSE_TO)
620            .append(IFSConstants.EQUAL_TO)
621            .append(IFSConstants.QUOTE)
622            .append(inResponseTo)
623            .append(IFSConstants.QUOTE)
624            .append(IFSConstants.SPACE)
625            .append(IFSConstants.SPACE);
626        }
627        
628        xml.append(IFSConstants.MAJOR_VERSION)
629        .append(IFSConstants.EQUAL_TO)
630        .append(IFSConstants.QUOTE)
631        .append(majorVersion)
632        .append(IFSConstants.QUOTE)
633        .append(IFSConstants.SPACE)
634        .append(IFSConstants.SPACE)
635        .append(IFSConstants.MINOR_VERSION)
636        .append(IFSConstants.EQUAL_TO)
637        .append(IFSConstants.QUOTE)
638        .append(minorVersion)
639        .append(IFSConstants.QUOTE)
640        .append(IFSConstants.SPACE)
641        .append(IFSConstants.SPACE)
642        .append(IFSConstants.ISSUE_INSTANT)
643        .append(IFSConstants.EQUAL_TO)
644        .append(IFSConstants.QUOTE)
645        .append(instantString)
646        .append(IFSConstants.QUOTE)
647        .append(IFSConstants.RIGHT_ANGLE);
648
649        if (signed) {
650            if (signatureString != null) {
651                xml.append(signatureString);
652            } else if (signature != null) {
653                signatureString = XMLUtils.print(signature);
654                xml.append(signatureString);
655            }
656        }
657        
658        if (providerId != null) {
659            xml.append(IFSConstants.LEFT_ANGLE)
660            .append(prefixLIB)
661            .append(IFSConstants.PROVIDER_ID)
662            .append(IFSConstants.RIGHT_ANGLE)
663            .append(providerId)
664            .append(IFSConstants.START_END_ELEMENT)
665            .append(prefixLIB)
666            .append(IFSConstants.PROVIDER_ID)
667            .append(IFSConstants.RIGHT_ANGLE);
668        }
669        
670        if (status != null) {
671            xml.append(status.toString(includeNS, true));
672        }
673        
674        if (relayState != null) {
675            xml.append(IFSConstants.LEFT_ANGLE)
676            .append(prefixLIB)
677            .append(IFSConstants.RELAY_STATE)
678            .append(IFSConstants.RIGHT_ANGLE)
679            .append(relayState)
680            .append(IFSConstants.START_END_ELEMENT)
681            .append(prefixLIB)
682            .append(IFSConstants.RELAY_STATE)
683            .append(IFSConstants.RIGHT_ANGLE);
684        }
685        
686        xml.append(IFSConstants.START_END_ELEMENT)
687        .append(prefixLIB)
688        .append(IFSConstants.LOGOUT_RESPONSE)
689        .append(IFSConstants.RIGHT_ANGLE);
690        
691        return xml.toString();
692    }
693    
694    /**
695     * Returns <code>FSLogoutResponse</code> object. The object
696     * is created by parsing an Base64 encode authentication
697     * request String.
698     *
699     * @param encodedRes the encode string
700     * @throws FSMsgException if there is an error creating this object.
701     * @throws SAMLException if there is an error creating this object.
702     */
703    public static FSLogoutResponse parseBASE64EncodedString(String encodedRes)
704    throws FSMsgException, SAMLException {
705        if (encodedRes != null){
706            String decodedNameRegRes = new String(Base64.decode(encodedRes));
707            if (FSUtils.debug.messageEnabled()) {
708                FSUtils.debug.message("FSLogoutResponse."
709                        + "parseBASE64EncodedString: decoded input string: "
710                        + decodedNameRegRes);
711            }
712            return parseXML(decodedNameRegRes);
713        } else {
714            if (FSUtils.debug.messageEnabled()) {
715                FSUtils.debug.message(
716                        "FSLogoutResponse.parseBASE64EncodedString"
717                        + ": null String passed in as argument.");
718            }
719            throw new FSMsgException("nullInput",null);
720        }
721    }
722    
723    /**
724     * Returns a Base64 Encoded String.
725     *
726     * @return a Base64 Encoded String.
727     * @throws FSMsgException if there is an error encoding the string.
728     */
729    public String toBASE64EncodedString() throws FSMsgException {
730        if ((responseID == null) || (responseID.length() == 0)){
731            responseID = FSUtils.generateID();
732            if (responseID == null) {
733                FSUtils.debug.error("FSLogoutResponse.toBASE64EncodedString: "
734                        + "couldn't generate ResponseID.");
735                throw new FSMsgException("errorGenerateID",null);
736            }
737        }
738        return Base64.encode(this.toXMLString().getBytes());
739    }
740    
741    /**
742     * Unsupported operation.
743     */
744    public void signXML() {
745    }
746    
747    /**
748     * Signs the <code>LogoutResponse</code>.
749     *
750     * @param certAlias the Certificate Alias.
751     * @throws XMLSignatureException if this object cannot be signed.
752     */
753    public void signXML(String certAlias) throws SAMLException {
754        FSUtils.debug.message("FSLogoutResponse.signXML: Called");
755        if (signed) {
756            if (FSUtils.debug.messageEnabled()) {
757                FSUtils.debug.message("FSLogoutResponse.signXML: "
758                        + "the assertion is already signed.");
759            }
760            throw new SAMLResponderException(FSUtils.BUNDLE_NAME,
761                    "alreadySigned",null);
762        }
763        if (certAlias == null || certAlias.length() == 0) {
764            throw new SAMLResponderException(FSUtils.BUNDLE_NAME,
765                    "cannotFindCertAlias",null);
766        }
767        try{
768            XMLSignatureManager manager = XMLSignatureManager.getInstance();
769            if (minorVersion == IFSConstants.FF_11_PROTOCOL_MINOR_VERSION) {
770                signatureString = manager.signXML(this.toXMLString(true, true),
771                        certAlias,
772                        IFSConstants.DEF_SIG_ALGO,
773                        IFSConstants.ID,
774                        this.id, false);
775            } else if (minorVersion ==
776                    IFSConstants.FF_12_PROTOCOL_MINOR_VERSION) {
777                signatureString =
778                        manager.signXML(this.toXMLString(true, true),
779                        certAlias, IFSConstants.DEF_SIG_ALGO,
780                        IFSConstants.RESPONSE_ID,
781                        this.getResponseID(), false);
782            } else {
783                if (FSUtils.debug.messageEnabled()) {
784                    FSUtils.debug.message("invalid minor version.");
785                }
786            }
787            
788            signature = XMLUtils.toDOMDocument(signatureString, FSUtils.debug)
789            .getDocumentElement();
790            
791            signed = true;
792            xmlString = this.toXMLString(true, true);
793        } catch (Exception e) {
794            throw new SAMLResponderException(FSUtils.BUNDLE_NAME,
795                    "signFailed",null);
796        }
797    }
798    
799    /**
800     * Sets the Signature.
801     *
802     * @param elem the Document Element.
803     * @return true if success otherwise false.
804     */
805    public boolean setSignature(Element elem) {
806        signatureString = XMLUtils.print(elem);
807        return super.setSignature(elem);
808    }
809    
810    /**
811     * Returns an URL Encoded String.
812     *
813     * @return a url encoded query string.
814     * @throws FSMsgException if there is an error.
815     */
816    public String toURLEncodedQueryString() throws FSMsgException {
817        if ((providerId == null) || (providerId.length() == 0)) {
818            FSUtils.debug.error("FSLogoutResponse."
819                    + "toURLEncodedQueryString: providerId is null in "
820                    + "the response ");
821            throw new FSMsgException("nullProviderIdInRequest",null);
822        }
823        if ((responseID == null) || (responseID.length() == 0)){
824            responseID = FSUtils.generateID();
825            if (responseID == null) {
826                FSUtils.debug.error("FSNameRegistrationRequest."
827                        + "toURLEncodedQueryString: couldn't generate "
828                        + "responseID.");
829                throw new FSMsgException("errorGenerateID",null);
830            }
831        }
832        
833        StringBuffer urlEncodedAuthnReq = new StringBuffer(300);
834        urlEncodedAuthnReq.append(IFSConstants.RESPONSE_ID)
835        .append(IFSConstants.EQUAL_TO)
836        .append(URLEncDec.encode(responseID))
837        .append(IFSConstants.AMPERSAND);
838        
839        if((inResponseTo != null) && (inResponseTo.length() > 0)) {
840            urlEncodedAuthnReq.append(IFSConstants.IN_RESPONSE_TO)
841            .append(IFSConstants.EQUAL_TO)
842            .append(URLEncDec.encode(inResponseTo))
843            .append(IFSConstants.AMPERSAND);
844        }
845        urlEncodedAuthnReq.append(IFSConstants.MAJOR_VERSION)
846        .append(IFSConstants.EQUAL_TO)
847        .append(majorVersion)
848        .append(IFSConstants.AMPERSAND)
849        .append(IFSConstants.MINOR_VERSION)
850        .append(IFSConstants.EQUAL_TO)
851        .append(minorVersion)
852        .append(IFSConstants.AMPERSAND);
853        
854        if (issueInstant != null) {
855            urlEncodedAuthnReq.append(IFSConstants.ISSUE_INSTANT)
856            .append(IFSConstants.EQUAL_TO)
857            .append(URLEncDec.encode(
858                    DateUtils.toUTCDateFormat(issueInstant)))
859                    .append(IFSConstants.AMPERSAND);
860        } else {
861            FSUtils.debug.error("FSLogoutResponse."
862                    + "toURLEncodedQueryString: issueInstant missing");
863            String[] args = { IFSConstants.ISSUE_INSTANT };
864            throw new FSMsgException("missingAttribute",args);
865            }
866            if(providerId != null && providerId.length() != 0) {
867                urlEncodedAuthnReq.append(IFSConstants.PROVIDER_ID)
868                .append(IFSConstants.EQUAL_TO)
869                .append(URLEncDec.encode(providerId))
870                .append(IFSConstants.AMPERSAND);
871            }
872            
873            if(relayState != null && relayState.length() != 0) {
874                urlEncodedAuthnReq.append(IFSConstants.RELAY_STATE)
875                .append(IFSConstants.EQUAL_TO)
876                .append(URLEncDec.encode(relayState))
877                .append(IFSConstants.AMPERSAND);
878            }
879            
880            if (status != null) {
881                urlEncodedAuthnReq.append(IFSConstants.VALUE)
882                .append(IFSConstants.EQUAL_TO)
883                .append(URLEncDec.encode(
884                        status.getStatusCode().getValue()))
885                        .append(IFSConstants.AMPERSAND);
886            }
887            return urlEncodedAuthnReq.toString();
888        }
889        
890        
891        /**
892         * Returns <code>FSLogoutResponse</code> object. The
893         * object is creating by parsing the <code>HttpServletRequest</code>
894         * object.
895         *
896         * @param request the <code>HttpServletRequest</code> object.
897         * @throws FSMsgException if there is an error creating this object.
898         * @throws SAMLException if there is an error.
899         */
900        public static FSLogoutResponse parseURLEncodedRequest(
901                HttpServletRequest request)
902                throws FSMsgException, SAMLException {
903            FSLogoutResponse retLogoutResponse = new FSLogoutResponse();
904            try {
905                FSUtils.debug.message("checking minor version");
906                retLogoutResponse.majorVersion =
907                        Integer.parseInt(
908                              request.getParameter(IFSConstants.MAJOR_VERSION));
909                retLogoutResponse.minorVersion =
910                        Integer.parseInt(
911                              request.getParameter(IFSConstants.MINOR_VERSION));
912            } catch(NumberFormatException ex){
913                throw new FSMsgException("invalidNumber",null);
914            }
915            
916            String requestID = request.getParameter(IFSConstants.RESPONSE_ID);
917            if (requestID != null) {
918                retLogoutResponse.responseID = requestID ;
919            } else {
920                String[] args = { IFSConstants.RESPONSE_ID };
921                throw new FSMsgException("missingAttribute",args);
922            }
923            retLogoutResponse.inResponseTo =
924                    request.getParameter(IFSConstants.IN_RESPONSE_TO);
925            
926            String instantString =
927                    request.getParameter(IFSConstants.ISSUE_INSTANT);
928            if (instantString == null || instantString.length() == 0) {
929                String[] args = { IFSConstants.ISSUE_INSTANT };
930                throw new FSMsgException("missingAttribute",args);
931            }
932            try{
933                retLogoutResponse.issueInstant =
934                        DateUtils.stringToDate(instantString);
935            } catch (ParseException e){
936                throw new FSMsgException("parseError",null);
937            }
938            FSUtils.debug.message(" get provider Id");
939            String providerID = request.getParameter(IFSConstants.PROVIDER_ID);
940            if (providerID != null) {
941                retLogoutResponse.providerId = providerID;
942                if (FSUtils.debug.messageEnabled()) {
943                    FSUtils.debug.message("ProviderID : "
944                            + retLogoutResponse.providerId);
945                }
946            } else {
947                if (FSUtils.debug.messageEnabled()) {
948                    FSUtils.debug.message("ProviderID : "
949                            + retLogoutResponse.providerId);
950                }
951                throw new FSMsgException("missingElement",null);
952            }
953            
954            String relayState = request.getParameter(IFSConstants.RELAY_STATE);
955            if (relayState != null) {
956                retLogoutResponse.relayState = relayState;
957                if (FSUtils.debug.messageEnabled()) {
958                    FSUtils.debug.message("RelayState:"
959                            + retLogoutResponse.relayState);
960                }
961            }
962            
963            String value = request.getParameter(IFSConstants.VALUE);
964            if (value != null){
965                if (FSUtils.debug.messageEnabled()) {
966                    FSUtils.debug.message("Status : " + value);
967                }
968                StatusCode statusCode = new StatusCode(value);
969                retLogoutResponse.status = new Status(statusCode);
970            } else {
971                if (FSUtils.debug.messageEnabled()) {
972                    FSUtils.debug.message("Status : " + value);
973                }
974                throw new FSMsgException("missingElement",null);
975            }
976            
977            FSUtils.debug.message("Returning Logout response Object");
978            return retLogoutResponse;
979        }
980    }




























































Copyright © 2010-2017, ForgeRock All Rights Reserved.