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: RequestAuthnContext.java,v 1.2 2008/06/25 05:46:47 qcheng Exp $
026 * Portions Copyrighted 2014 ForgeRock AS
027 */
028
029package com.sun.identity.federation.message.common;
030
031import static org.forgerock.http.util.Uris.urlEncodeQueryParameterNameOrValue;
032
033import com.sun.identity.federation.common.FSUtils;
034import com.sun.identity.federation.common.IFSConstants;
035import com.sun.identity.saml.common.SAMLConstants;
036import com.sun.identity.shared.xml.XMLUtils;
037import java.util.ArrayList;
038import java.util.Collections;
039import java.util.Iterator;
040import java.util.List;
041import java.util.StringTokenizer;
042import javax.servlet.http.HttpServletRequest;
043import org.w3c.dom.Element;
044import org.w3c.dom.Node;
045import org.w3c.dom.NodeList;
046
047
048/**
049 * This class <code>RequestAuthnContext</code> represents the requesting
050 * Authentication Context as part of the <code>FSAuthnRequest</code>.
051 *
052 * @supported.all.api
053 * @deprecated since 12.0.0
054 */
055@Deprecated
056public class RequestAuthnContext {
057
058    private List authnContextClassRefList = null;
059    private List authnContextStatementRefList = null;
060    private String authnContextComparison = null;
061    private int minorVersion = 0;
062    
063    /**
064     * Constructor to create <code>RequestAuthnContext</code> object.
065     *
066     * @param authnContextClassRefList 
067     *        Ordered list of AuthnContext Classes Refs.
068     * @param authnContextStatementRefList 
069     *        Ordered list of AuthnContext Statement Refs.
070     *        Note: authnContextClassRefList and authContextStatementRefList
071     *        are mutually exclusive lists.
072     * @param authnContextComparison AuthnContext Comparison Type.
073     *        Possible values are  <code>exact</code>, <code>minimum<code>,
074     *        <code>better</code> and <code>maximum</code>.
075     */
076    public RequestAuthnContext (
077        List authnContextClassRefList,
078        List authnContextStatementRefList,
079        String authnContextComparison) {
080
081        this.authnContextStatementRefList = authnContextStatementRefList;
082        this.authnContextClassRefList = authnContextClassRefList;
083        this.authnContextComparison = authnContextComparison;
084    }
085
086    /**
087     * Default constructor.
088     */
089    public RequestAuthnContext(){}
090    
091    /**
092     * Constructor to create <code>RequestAuthnContext</code> object from
093     * Docuemnt Element.
094     *
095     * @param root the Document Element.
096     * @throws FSMsgException on error.
097     */
098    public RequestAuthnContext(Element root) throws FSMsgException {
099        if(root == null) {
100            FSUtils.debug.message("AuthnContext.parseXML: null input.");
101            throw new FSMsgException("nullInput",null);
102        }
103        
104        String tag = root.getLocalName();
105        
106        if(tag == null) {
107            FSUtils.debug.error("AuthnContext.parseXML: wrong input.");
108            throw new FSMsgException("wrongInput",null);
109        }
110        
111        if(!tag.equals("RequestAuthnContext") && !tag.equals("AuthnContext")) {
112            FSUtils.debug.error("AuthnContext.parseXML: wrong input.");
113            throw new FSMsgException("wrongInput",null);
114        }
115        
116        NodeList nl = root.getChildNodes();
117        int length = nl.getLength();
118        
119        for(int i = 0; i < length; i++) {
120            Node child = nl.item(i);
121            String childName = child.getLocalName();
122            
123            if(childName == null) {
124                continue;
125            }
126            
127            if(childName.equals("AuthnContextClassRef")) {
128                if(authnContextStatementRefList != null) {
129                    FSUtils.debug.error("AuthnContext(Element): Should"
130                            + "contain either <AuthnContextStatementRef> or "
131                            + "<AuthnContextClassRef>");
132                    throw new FSMsgException("wrongInput",null);
133                }
134                
135                if(authnContextClassRefList == null ||
136                        authnContextClassRefList == Collections.EMPTY_LIST) {
137                    authnContextClassRefList = new ArrayList();
138                }
139                
140                authnContextClassRefList.add(
141                        XMLUtils.getElementValue((Element) child));
142                
143            } else if (childName.equals("AuthnContextStatementRef")) {
144                
145                if(authnContextClassRefList != null) {
146                    FSUtils.debug.error("AuthnContext(Element): Should"
147                            + "contain either <AuthnContextStatementRef> or "
148                            + "<AuthnContextClassRef>");
149                    throw new FSMsgException("wrongInput",null);
150                }
151                
152                if(authnContextStatementRefList == null ||
153                       authnContextStatementRefList == Collections.EMPTY_LIST) {
154                    authnContextStatementRefList = new ArrayList();
155                }
156                
157                authnContextStatementRefList.add(
158                        XMLUtils.getElementValue((Element) child));
159                
160            } else if(childName.equals("AuthnContextComparison")) {
161                
162                authnContextComparison = XMLUtils.getElementValue(
163                        (Element)child);
164            }
165        }
166    }
167    
168    /**
169     * Returns <code>List</code> of <code>AuthnContext</code> Class References.
170     *
171     * @return <code>List</code> of <code>AuthnContext</code> Class Reference
172     *         classes.
173     * @see #setAuthnContextClassRefList(List)
174     */
175    public List getAuthnContextClassRefList() {
176        return authnContextClassRefList;
177    }
178    
179    /**
180     * Sets a <code>List</code> of  <code>AuthnContext</code> Class References.
181     *
182     * @param authnContextClassRefList a <code>List</code> of  
183     *        <code>AuthnContext</code> Class References.
184     * @see #getAuthnContextClassRefList
185     */
186    public void setAuthnContextClassRefList(
187        List authnContextClassRefList) {
188
189        this.authnContextClassRefList = authnContextClassRefList;
190    }
191    
192    /**
193     * Returns a <code>List</code> of <code>AuthnContext</code> Statement
194     * References.
195     *
196     * @return a <code>List</code> of <code>AuthnContext</code> Statement
197     *         References.
198     * @see #setAuthnContextStatementRefList(List)
199     */
200    public List getAuthnContextStatementRefList() {
201        return this.authnContextStatementRefList;
202    }
203
204    /**
205     * Sets a <code>List</code> of <code>AuthnContext</code> Statement 
206     * References.
207     *
208     * @param authnContextStatementRefList a <code>List</code> of
209     *        <code>AuthnContext</code> Statement References.
210     * @see #getAuthnContextStatementRefList
211     */
212    public void setAuthnContextStatementRefList(
213                    List authnContextStatementRefList ) {
214        this.authnContextStatementRefList = authnContextStatementRefList;
215    }
216
217    /**
218     * Returns the <code>AuthnContext</code> Comparison type.
219     *
220     * @return authnContextComparison the <code>AuthnContext</code> Comparison 
221     *          type.
222     * @see #setAuthnContextComparison(String)
223     */
224    public String getAuthnContextComparison() {
225        return authnContextComparison;
226    }
227
228    /**
229     * Sets the <code>AuthnContext</code> comparison type.
230     *
231     * @param authnContextComparison the <code>AuthnContext</code> comparison 
232     *        type.
233     * @see #getAuthnContextComparison
234     */
235    public void setAuthnContextComparison(String authnContextComparison) {
236        this.authnContextComparison = authnContextComparison;
237    }
238
239    /**
240     * Returns the <code>MinorVersion</code>.
241     *
242     * @return the <code>MinorVersion</code>.
243     * @see #setMinorVersion(int)
244     */
245    public int getMinorVersion() {
246       return minorVersion;
247    }
248
249    /**
250     * Sets the <code>MinorVersion</code>.
251     *
252     * @param minorVersion the <code>MinorVersion</code>.
253     * @see #getMinorVersion()
254     */
255    public void setMinorVersion(int minorVersion) {
256        this.minorVersion = minorVersion;
257    }
258
259    /**
260     * Returns a String representation of the Logout Response.
261     *
262     * @return a string containing the valid XML for this element
263     * @throws FSMsgException if there is an error converting
264     *         this object ot a string.
265     */
266    public String toXMLString() throws FSMsgException {
267        return this.toXMLString(true, false);
268    }
269    
270    /**
271     * Returns a String representation of this object.
272     *
273     * @param includeNS : Determines whether or not the namespace qualifier
274     *        is prepended to the Element when converted
275     * @param declareNS : Determines whether or not the namespace is declared
276     *        within the Element.
277     * @return a string containing the valid XML for this element
278     * @throws FSMsgException if there is an error converting
279     *         this object to a string.
280     */
281    public String toXMLString(boolean includeNS, boolean declareNS) 
282                              throws FSMsgException {
283      return toXMLString(includeNS, declareNS, false);
284    }
285   
286     /**
287     * Returns a String representation of the Logout Response.
288     *
289     * @param includeNS Determines whether or not the namespace qualifier
290     *        is prepended to the Element when converted
291     * @param declareNS Determines whether or not the namespace is declared
292     *        within the Element.
293     * @param includeHeader Determines whether the output include the xml
294     *        declaration header.
295     * @return a string containing the valid XML for this element
296     * @throws FSMsgException if there is an error converting
297     *         this object ot a string.
298     */
299    public String toXMLString(boolean includeNS, boolean declareNS, 
300                              boolean includeHeader) throws FSMsgException {
301
302        StringBuffer xml = new StringBuffer(300);
303
304        if (includeHeader) {
305            xml.append("<?xml version=\"1.0\" encoding=\"").
306                append(SAMLConstants.DEFAULT_ENCODING).append("\" ?>\n");
307        }
308
309        String prefixAC = "";
310        String prefixLIB = "";
311        String uriAC = "";
312        String uriLIB = "";
313
314        if (includeNS) {
315            prefixLIB = IFSConstants.LIB_PREFIX;
316            prefixAC = IFSConstants.AC_PREFIX;
317        }
318
319        if (declareNS) {
320            if(minorVersion == IFSConstants.FF_12_PROTOCOL_MINOR_VERSION) {
321               uriLIB = IFSConstants.LIB_12_NAMESPACE_STRING;
322               uriAC = IFSConstants.AC_12_NAMESPACE_STRING;
323            } else {
324               uriLIB = IFSConstants.LIB_NAMESPACE_STRING;
325               uriAC = IFSConstants.AC_NAMESPACE_STRING;
326            }
327        }
328        
329        xml.append("<").append(prefixLIB);
330
331        if(minorVersion == IFSConstants.FF_12_PROTOCOL_MINOR_VERSION) {
332           xml.append("RequestAuthnContext");
333        } else {
334           xml.append("AuthnContext");
335        }
336
337        xml.append(uriLIB).append(">\n");
338
339        if ((authnContextClassRefList != null) && 
340            (authnContextClassRefList != Collections.EMPTY_LIST)) {
341
342            if((authnContextStatementRefList != null) && 
343               (authnContextClassRefList != Collections.EMPTY_LIST)) {
344               throw new FSMsgException("ExclusiveEntries",null);
345            }
346
347            Iterator j = authnContextClassRefList.iterator();
348            while (j.hasNext()) {
349                xml.append("<").append(prefixLIB).
350                    append("AuthnContextClassRef").append(">"); 
351                xml.append((String)j.next());
352                xml.append("</").append(prefixLIB).
353                    append("AuthnContextClassRef").append(">\n"); 
354            }
355        }
356        
357        
358        if ((authnContextStatementRefList != null) && 
359            (authnContextStatementRefList != Collections.EMPTY_LIST)) {
360
361            Iterator j = authnContextStatementRefList.iterator();
362            while (j.hasNext()) {
363                xml.append("<").append(prefixLIB).
364                    append("AuthnContextStatementRef").append(">"); 
365                xml.append((String)j.next());
366                xml.append("</").append(prefixLIB).
367                    append("AuthnContextStatementRef").append(">\n"); 
368            }
369        }
370
371        if(minorVersion == IFSConstants.FF_12_PROTOCOL_MINOR_VERSION) {
372           xml.append("<").append(prefixLIB)
373              .append("AuthnContextComparison").append(">")
374              .append(authnContextComparison)
375              .append("</").append(prefixLIB)
376              .append("AuthnContextComparison").append(">\n");
377        }
378        
379        xml.append("</").append(prefixLIB);
380        if(minorVersion == IFSConstants.FF_12_PROTOCOL_MINOR_VERSION) {
381           xml.append("RequestAuthnContext").append(">\n");
382        } else {
383           xml.append("AuthnContext").append(">\n");
384        }
385
386        return xml.toString();    
387    }   
388   
389    /**
390     * Returns <code>RequestAuthnContext</code> object. The
391     * object is creating by parsing the <code>HttpServletRequest</code>
392     * object.
393     *
394     * @param request the <code>HttpServletRequest</code> object.
395     * @return <code><RequestAuthnContext/code> object.
396     * @throws FSMsgException if there is an error
397     *         creating <code>RequestAuthnContext</code> object.
398     */
399    public static RequestAuthnContext parseURLEncodedRequest(
400           HttpServletRequest request, int minorVersion)
401           throws FSMsgException {
402        RequestAuthnContext retAuthnContext = new RequestAuthnContext();
403        String strAuthnContextClassRef = 
404               request.getParameter("AuthnContextClassRef");
405
406        if(strAuthnContextClassRef != null){
407           StringTokenizer st = new StringTokenizer(strAuthnContextClassRef);
408
409            while (st.hasMoreTokens()) {
410               if (retAuthnContext.authnContextClassRefList == null) {
411                   retAuthnContext.authnContextClassRefList = new ArrayList();
412               }                    
413               retAuthnContext.authnContextClassRefList.add(st.nextToken());
414            }
415        }
416        
417        String strAuthnContextStatementRef = 
418               request.getParameter("AuthnContextStatementRef");
419
420        if(strAuthnContextStatementRef != null){
421            StringTokenizer st = 
422                new StringTokenizer(strAuthnContextStatementRef);
423
424            while (st.hasMoreTokens()) {
425               if (retAuthnContext.authnContextStatementRefList == null) {
426                   retAuthnContext.authnContextStatementRefList = 
427                                   new ArrayList();
428               }                    
429               retAuthnContext.authnContextStatementRefList.add(st.nextToken());
430            }
431        }
432
433        String strAuthnContextComparison =
434               request.getParameter("AuthnContextComparison");
435
436        if(strAuthnContextComparison != null) {
437           retAuthnContext.setAuthnContextComparison(strAuthnContextComparison);
438        }
439
440        retAuthnContext.setMinorVersion(minorVersion);
441        
442        return retAuthnContext;        
443    }
444    
445      
446    /**
447     * Returns an URL Encoded String.
448     *
449     * @return a url encoded query string.
450     * @throws FSMsgException if there is an error.
451     */
452    public String toURLEncodedQueryString() throws FSMsgException {
453
454       StringBuffer urlEncodedAuthnReq = new StringBuffer(300);
455
456       if ((authnContextClassRefList != null) && 
457           (!authnContextClassRefList.isEmpty())) {
458
459           if((authnContextStatementRefList != null) &&
460              (!authnContextStatementRefList.isEmpty())) { 
461               throw new FSMsgException("ExclusiveEntries",null);
462           }
463
464           StringBuffer strEncodedString = new StringBuffer(100); 
465           Iterator j = authnContextClassRefList.iterator();
466           strEncodedString.append((String)j.next());
467
468           while(j.hasNext()) {
469               strEncodedString.append(" ").append((String)j.next());
470           }
471
472           urlEncodedAuthnReq.append("AuthnContextClassRef=").
473                    append(urlEncodeQueryParameterNameOrValue(strEncodedString.toString())).
474                    append(IFSConstants.AMPERSAND);
475        }
476       
477       if ((authnContextStatementRefList != null) && 
478            (!authnContextStatementRefList.isEmpty())) {
479
480            StringBuffer strEncodedString = new StringBuffer(100); 
481            Iterator j = authnContextStatementRefList.iterator();
482
483            strEncodedString.append((String)j.next());
484            while (j.hasNext()) {
485                strEncodedString.append(" ").append((String)j.next());
486            }
487
488            urlEncodedAuthnReq.append("AuthnContextClassRef=").
489                   append(urlEncodeQueryParameterNameOrValue(strEncodedString.toString())).
490                   append(IFSConstants.AMPERSAND);
491        }
492
493        if(minorVersion == IFSConstants.FF_12_PROTOCOL_MINOR_VERSION) {
494            if(authnContextComparison != null) {
495                   urlEncodedAuthnReq.append("AuthnContextComparison=").
496                   append(urlEncodeQueryParameterNameOrValue(authnContextComparison)).
497                   append(IFSConstants.AMPERSAND);
498            }
499        }
500        return urlEncodedAuthnReq.toString();         
501    } 
502}