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: FSNameIdentifierMappingResponse.java,v 1.2 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.xml.XMLUtils;
032
033import com.sun.identity.shared.Constants;
034import com.sun.identity.shared.DateUtils;
035import com.sun.identity.common.SystemConfigurationUtil;
036
037import com.sun.identity.federation.common.FSUtils;
038import com.sun.identity.federation.common.IFSConstants;
039import com.sun.identity.federation.message.common.FSMsgException;
040
041import com.sun.identity.saml.assertion.NameIdentifier;
042
043import com.sun.identity.saml.common.SAMLConstants;
044import com.sun.identity.saml.common.SAMLException;
045import com.sun.identity.saml.common.SAMLResponderException;
046
047import com.sun.identity.saml.protocol.AbstractResponse;
048import com.sun.identity.saml.protocol.Status;
049
050import com.sun.identity.saml.xmlsig.XMLSignatureManager;
051
052import java.util.Date;
053import java.util.List;
054
055import org.w3c.dom.Document;
056import org.w3c.dom.Element;
057import org.w3c.dom.Node;
058import org.w3c.dom.NodeList;
059
060/**
061 * The class <code>FSNameIdentifierMappingResponse</code> is used to
062 * create , parse the <code>NameIdentifierMappingResponse</code>.
063 *
064 * @supported.all.api
065 * @deprecated since 12.0.0
066 */
067@Deprecated
068public class FSNameIdentifierMappingResponse extends AbstractResponse {
069    
070    private String providerID;
071    private Status status;
072    private NameIdentifier nameIdentifier;
073    private int minorVersion = IFSConstants.FF_12_PROTOCOL_MINOR_VERSION;
074    private String signatureString;
075    
076    /**
077     * Constructor to create <code>FSNameIdentifierMappingResponse</code> object.
078     *
079     * @param providerID the value of <code>ProviderID</code> attribute.
080     * @param inResponseTo the value of <code>InResponseTo</code> attribute.
081     * @param status the <code>Status</code> object.
082     * @param nameIdentifier the resulting mapped identifier,
083     *        <code>NameIdentifier</code>, for the desired identity federation.
084     * @throws FSMsgException on an error.
085     */
086    public FSNameIdentifierMappingResponse(String providerID,
087            String inResponseTo, Status status,
088            NameIdentifier nameIdentifier) throws FSMsgException {
089        this.providerID = providerID;
090        this.inResponseTo = inResponseTo;
091        this.status = status;
092        this.nameIdentifier = nameIdentifier;
093        this.responseID = FSUtils.generateID();
094        setIssueInstant(new Date());
095    }
096    
097    /**
098     * Constructor to create <code>FSNameIdentifierMappingResponse</code> object.
099     * This object is created from the Document Element.
100     *
101     * @param root the <code>NameIdentifierMappingResponse</code> Document
102     *        Element
103     * @throws FSMsgException if there is an error creating the object.
104     */
105    public FSNameIdentifierMappingResponse(Element root)
106    throws FSMsgException {
107        if (root == null) {
108            FSUtils.debug.message(
109                    "FSNameIdentifierMappingResponse: null element input");
110            throw new FSMsgException("nullInputParameter",null);
111        }
112        String tag = null;
113        if (((tag = root.getLocalName()) == null) ||
114                (!tag.equals("NameIdentifierMappingResponse"))) {
115            FSUtils.debug.message(
116                    "FSNameIdentifierMappingRequest: wrong input");
117            throw new FSMsgException("wrongInput",null);
118        }
119        
120        // get IssueInstant
121        String instantString = root.getAttribute(IFSConstants.ISSUE_INSTANT);
122        if (instantString==null || instantString.length()==0) {
123            FSUtils.debug.error("FSNameIdentifierMappingResponse: " +
124                    "missing IssueInstant");
125            String[] args = { IFSConstants.ISSUE_INSTANT };
126            throw new FSMsgException("missingAttribute",args);
127        } else {
128            try {
129                issueInstant = DateUtils.stringToDate(instantString);
130            } catch (Exception e) {
131                FSUtils.debug.error("FSNameIdentifierMappingResponse: " +
132                        "could not parse IssueInstant.", e);
133                throw new FSMsgException("wrongInput",null);
134            }
135        }
136        
137        // get ResponseID
138        responseID = root.getAttribute(IFSConstants.RESPONSE_ID);
139        if ((responseID == null) || (responseID.length() < 1)) {
140            FSUtils.debug.error("FSNameIdentifierMappingResponse: " +
141                    "response doesn't have ResponseID");
142            String[] args = { IFSConstants.RESPONSE_ID };
143            throw new FSMsgException("missingAttribute",args);
144        }
145        
146        // get InResponseTo
147        inResponseTo = root.getAttribute(IFSConstants.IN_RESPONSE_TO);
148        if (inResponseTo == null) {
149            FSUtils.debug.error("FSNameIdentifierMappingResponse: " +
150                    "response doesn't have InResponseTo");
151            String[] args = { IFSConstants.IN_RESPONSE_TO };
152            throw new FSMsgException("missingAttribute",args);
153        }
154        
155        // get and check versions
156        parseMajorVersion(root.getAttribute(IFSConstants.MAJOR_VERSION));
157        parseMinorVersion(root.getAttribute(IFSConstants.MINOR_VERSION));
158        
159        // get ProviderID, Status & NameIdentifier
160        NodeList nl = root.getChildNodes();
161        Node child;
162        String childName;
163        int length = nl.getLength();
164        for (int i = 0; i < length; i++) {
165            child = nl.item(i);
166            if ((childName = child.getLocalName()) != null) {
167                if (childName.equals(IFSConstants.STATUS)) {
168                    try {
169                        status = new Status((Element) child);
170                    } catch (SAMLException se) {
171                        FSUtils.debug.error("FSNameIdentifierMappingResponse:" +
172                                " unable to initialize Status", se);
173                        throw new FSMsgException("statusCreateError",null,se);
174                    }
175                } else if (childName.equals(IFSConstants.PROVIDER_ID)) {
176                    providerID = XMLUtils.getElementValue((Element) child);
177                } else if (childName.equals(IFSConstants.NAME_IDENTIFIER)) {
178                    try {
179                        nameIdentifier =
180                                new NameIdentifier((Element) child);
181                    } catch (SAMLException samle) {
182                        FSUtils.debug.error("FSNameIdentifierMappingResponse:" +
183                                " unable to initialize NameIdentifier", samle);
184                        throw new FSMsgException("nameIdentifierCreateError",
185                                null,samle);
186                    }
187                }
188            }
189        }
190        
191        // get signature
192        List signs = XMLUtils.getElementsByTagNameNS1(
193                root,
194                SAMLConstants.XMLSIG_NAMESPACE_URI,
195                SAMLConstants.XMLSIG_ELEMENT_NAME);
196        int signsSize = signs.size();
197        if (signsSize == 1) {
198            Element elem = (Element)signs.get(0);
199            setSignature(elem);
200            signed = true;
201        } else if (signsSize != 0) {
202            FSUtils.debug.error("FSNameIdentifierMappingResponse: " +
203                    "included more than one Signature element.");
204            throw new FSMsgException("moreElement",null);
205        }
206    }
207    
208    /**
209     * Creates <code>FSNameIdentifierMappingResponse</code> object.
210     * This object is created by parsing the <code>XML</code> string.
211     *
212     * @param xml the <code>XML</code> string to be parse.
213     * @return the <code>FSNameIdentifierMappingResponse</code> object.
214     * @throws FSMsgException if there is an error in parsing the
215     *            <code>XML</code> string.
216     */
217    public static FSNameIdentifierMappingResponse parseXML(String xml)
218    throws FSMsgException {
219        Document doc = XMLUtils.toDOMDocument(xml, FSUtils.debug);
220        if (doc == null) {
221            FSUtils.debug.error("FSNameIdentifierMappingResponse.parseXML: " +
222                    "error while parsing input xml string");
223            throw new FSMsgException("parseError",null);
224        }
225        Element root = doc.getDocumentElement();
226        return new FSNameIdentifierMappingResponse(root);
227    }
228    
229    /**
230     * Returns the value of <code>ProviderID</code> attribute.
231     *
232     * @return the value of <code>ProviderID</code> attribute.
233     */
234    public String getProviderID() {
235        return providerID;
236    }
237    
238    /**
239     * Returns the <code>Status</code>.
240     *
241     * @return the <code>Status</code>.
242     */
243    public Status getStatus() {
244        return status;
245    }
246    
247    /**
248     * Returns the <code>NameIdentifier</code> object. This is the resulting
249     * mapped name identifier for the desired identity federation.
250     *
251     * @return <code>NameIdentifier</code> object, the resulting mapped name
252     *          identifier for the desired identity federation
253     */
254    public NameIdentifier getNameIdentifier() {
255        return nameIdentifier;
256    }
257    
258    /**
259     * Sets the <code>MajorVersion</code> by parsing the version string.
260     *
261     * @param version a String representing the <code>MajorVersion</code> to
262     *        be set.
263     * @throws FSMsgException on error.
264     */
265    private void parseMajorVersion(String version) throws FSMsgException {
266        try {
267            majorVersion = Integer.parseInt(version);
268        } catch (NumberFormatException e) {
269            if (FSUtils.debug.messageEnabled()) {
270                FSUtils.debug.message("FSNameIdentifierMappingResponse." +
271                        "parseMajorVersion:invalid MajorVersion:" + version, e);
272            }
273            throw new FSMsgException("wrongInput",null);
274        }
275        
276        if (majorVersion != SAMLConstants.PROTOCOL_MAJOR_VERSION) {
277            if (majorVersion > SAMLConstants.PROTOCOL_MAJOR_VERSION) {
278                if (FSUtils.debug.messageEnabled()) {
279                    FSUtils.debug.message("FSNameIdentifierMappingResponse." +
280                            "parseMajorVersion: MajorVersion is too high");
281                }
282                throw new FSMsgException("requestVersionTooHigh",null);
283            } else {
284                if (FSUtils.debug.messageEnabled()) {
285                    FSUtils.debug.message("FSNameIdentifierMappingResponse." +
286                            "parseMajorVersion: MajorVersion is too low");
287                }
288                throw new FSMsgException("requestVersionTooLow",null);
289            }
290        }
291    }
292    
293    /**
294     * Sets the <code>MinorVersion</code> by parsing the version string.
295     *
296     * @param minorVer a String representing the <code>MinorVersion</code> to
297     *        be set.
298     * @throws FSMsgException when the version mismatchs.
299     */
300    private void parseMinorVersion(String version) throws FSMsgException {
301        try {
302            minorVersion = Integer.parseInt(version);
303        } catch (NumberFormatException e) {
304            if (FSUtils.debug.messageEnabled()) {
305                FSUtils.debug.message("FSNameIdentifierMappingResponse." +
306                        "parseMinorVersion:invalid MinorVersion:" + version, e);
307            }
308            throw new FSMsgException("wrongInput",null);
309        }
310        if (minorVersion > IFSConstants.FF_12_PROTOCOL_MINOR_VERSION) {
311            if (FSUtils.debug.messageEnabled()) {
312                FSUtils.debug.message("FSNameIdentifierMappingResponse." +
313                    "parseMinorVersion: MinorVersion is too high");
314            }
315            throw new FSMsgException("requestVersionTooHigh",null);
316        } else if (minorVersion < IFSConstants.FF_11_PROTOCOL_MINOR_VERSION) {
317            if (FSUtils.debug.messageEnabled()) {
318                FSUtils.debug.message("FSNameIdentifierMappingResponse." +
319                    "parseMinorVersion: MinorVersion is too low");
320            }
321            throw new FSMsgException("requestVersionTooLow",null);
322        }
323    }
324    
325    /**
326     * Signs the XML document representing
327     * <code>NameIdentifierMappingResponse</code> using the certificate
328     * indicated by the property "com.sun.identity.saml.xmlsig.certalias"
329     * in AMConfig.properties file.
330     *
331     * @throws SAMLException if there is an error signing
332     *            the <code>XML</code> string.
333     */
334    public void signXML() throws SAMLException {
335        String certAlias = SystemConfigurationUtil.getProperty(
336                Constants.SAML_XMLSIG_CERT_ALIAS);
337        signXML(certAlias);
338    }
339    
340    /**
341     * Signs the <code>XML</code> document representing
342     * <code>NameIdentifierMappingResponse</code> using the specified
343     * certificate.
344     *
345     * @param certAlias the alias/name of the certificate used for signing
346     *                   the XML document
347     * @throws SAMLException if there is an error signing
348     *            the <code>XML</code> string or if the message is already
349     *            signed.
350     */
351    public void signXML(String certAlias) throws SAMLException {
352        FSUtils.debug.message("FSNameIdentifierMappingResponse.signXML");
353        if (signed) {
354            if (FSUtils.debug.messageEnabled()) {
355                FSUtils.debug.message("FSNameIdentifierMappingResponse.signXML:"
356                        + " the response is already signed.");
357            }
358            throw new SAMLResponderException(FSUtils.BUNDLE_NAME,
359                    "alreadySigned",null);
360        }
361        if (certAlias == null || certAlias.length() < 1) {
362            if (FSUtils.debug.messageEnabled()) {
363                FSUtils.debug.message("FSNameIdentifierMappingResponse.signXML:"
364                        + " null certAlias");
365            }
366            throw new SAMLResponderException(FSUtils.BUNDLE_NAME,
367                    "cannotFindCertAlias",null);
368        }
369        try {
370            XMLSignatureManager manager = XMLSignatureManager.getInstance();
371            signatureString = manager.signXML(this.toXMLString(true, true),
372                    certAlias, (String)null,
373                    IFSConstants.RESPONSE_ID,
374                    this.getResponseID(), false);
375            signature = XMLUtils.toDOMDocument(signatureString, FSUtils.debug)
376            .getDocumentElement();
377            signed = true;
378        } catch (Exception e){
379            FSUtils.debug.error("FSNameIdentifierMappingResponse.signXML: " +
380                    "unable to sign", e);
381            throw new SAMLResponderException(
382                    FSUtils.BUNDLE_NAME,"signFailed",null);
383        }
384    }
385    
386    /**
387     * Returns the string representation of this object.
388     *
389     * @return An XML String representing the object.
390     * @throws FSMsgException on error.
391     */
392    public String toXMLString()  throws FSMsgException {
393        return toXMLString(true, true);
394    }
395    
396    /**
397     * Returns a String representation of this object.
398     *
399     * @param includeNS : Determines whether or not the namespace qualifier
400     *        is prepended to the Element when converted
401     * @param declareNS : Determines whether or not the namespace is declared
402     *        within the Element.
403     * @return a string containing the valid XML for this element
404     * @throws FSMsgException if there is an error converting
405     *         this object ot a string.
406     */
407    
408    public String toXMLString(boolean includeNS, boolean declareNS)
409    throws FSMsgException {
410        return toXMLString(includeNS, declareNS, false);
411    }
412    
413    /**
414     * Returns a String representation of this object.
415     *
416     * @param includeNS Determines whether or not the namespace qualifier
417     *        is prepended to the Element when converted
418     * @param declareNS Determines whether or not the namespace is declared
419     *        within the Element.
420     * @param includeHeader Determines whether the output include the xml
421     *        declaration header.
422     * @return a string containing the valid XML for this element
423     * @throws FSMsgException if there is an error converting
424     *         this object ot a string.
425     */
426    public String toXMLString(boolean includeNS, boolean declareNS,
427            boolean includeHeader) throws FSMsgException {
428        
429        String prefixLIB = "";
430        String uriLIB = "";
431        String uriSAML = "";
432        if (includeNS) {
433            prefixLIB = IFSConstants.LIB_PREFIX;
434        }
435        if (declareNS) {
436            uriLIB = IFSConstants.LIB_12_NAMESPACE_STRING;
437            uriSAML = IFSConstants.assertionDeclareStr;
438        }
439        String instantString = null;
440        try {
441            instantString = DateUtils.toUTCDateFormat(issueInstant);
442        } catch (Exception e) {
443            FSUtils.debug.error("FSNameIdentifierMappingResponse.toXMLString:" +
444                    " could not convert issueInstant to String.", e);
445        }
446        // construct xml response
447        StringBuffer xml = new StringBuffer(1000);
448        if (includeHeader) {
449            xml.append(IFSConstants.XML_PREFIX)
450            .append(SAMLConstants.DEFAULT_ENCODING)
451            .append(IFSConstants.QUOTE)
452            .append(IFSConstants.SPACE)
453            .append(IFSConstants.QUESTION_MARK)
454            .append(IFSConstants.RIGHT_ANGLE)
455            .append(IFSConstants.NL);
456        }
457        xml.append(IFSConstants.LEFT_ANGLE)
458        .append(prefixLIB)
459        .append(IFSConstants.NAMEID_MAPPING_RESPONSE)
460        .append(uriLIB).append(uriSAML)
461        .append(IFSConstants.SPACE)
462        .append(IFSConstants.RESPONSE_ID)
463        .append(IFSConstants.EQUAL_TO)
464        .append(IFSConstants.QUOTE)
465        .append(responseID)
466        .append(IFSConstants.QUOTE)
467        .append(IFSConstants.SPACE)
468        .append(IFSConstants.IN_RESPONSE_TO)
469        .append(IFSConstants.EQUAL_TO)
470        .append(IFSConstants.QUOTE)
471        .append(inResponseTo)
472        .append(IFSConstants.QUOTE)
473        .append(IFSConstants.SPACE)
474        .append(IFSConstants.SPACE)
475        .append(IFSConstants.MAJOR_VERSION)
476        .append(IFSConstants.EQUAL_TO)
477        .append(IFSConstants.QUOTE)
478        .append(majorVersion)
479        .append(IFSConstants.EQUAL_TO)
480        .append(IFSConstants.QUOTE)
481        .append(IFSConstants.SPACE)
482        .append(IFSConstants.SPACE)
483        .append(IFSConstants.MINOR_VERSION)
484        .append(IFSConstants.EQUAL_TO)
485        .append(IFSConstants.QUOTE)
486        .append(minorVersion)
487        .append(IFSConstants.QUOTE)
488        .append(IFSConstants.SPACE)
489        .append(IFSConstants.SPACE)
490        .append(IFSConstants.ISSUE_INSTANT)
491        .append(IFSConstants.EQUAL_TO)
492        .append(instantString)
493        .append(IFSConstants.QUOTE)
494        .append(IFSConstants.SPACE)
495        .append(IFSConstants.RIGHT_ANGLE);
496        if (signed) {
497            if (signatureString != null) {
498                xml.append(signatureString);
499            } else if (signature != null) {
500                signatureString = XMLUtils.print(signature);
501                xml.append(signatureString);
502            }
503        }
504        xml.append(IFSConstants.LEFT_ANGLE)
505        .append(prefixLIB)
506        .append(IFSConstants.PROVIDER_ID)
507        .append(IFSConstants.RIGHT_ANGLE)
508        .append(providerID)
509        .append(IFSConstants.START_END_ELEMENT)
510        .append(prefixLIB)
511        .append(IFSConstants.PROVIDER_ID)
512        .append(IFSConstants.RIGHT_ANGLE)
513        .append(status.toString(includeNS, true));
514        
515        if (nameIdentifier != null) {
516            xml.append(nameIdentifier.toString());
517        }
518        xml.append(IFSConstants.START_END_ELEMENT)
519        .append(prefixLIB)
520        .append(IFSConstants.NAMEID_MAPPING_RESPONSE)
521        .append(IFSConstants.RIGHT_ANGLE);
522        
523        return xml.toString();
524    }
525}




























































Copyright © 2010-2017, ForgeRock All Rights Reserved.