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: FSAuthenticationStatement.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.common.FSUtils;
033import com.sun.identity.federation.message.common.AuthnContext;
034import com.sun.identity.federation.message.common.FSMsgException;
035import com.sun.identity.saml.assertion.AuthenticationStatement;
036import com.sun.identity.saml.assertion.AuthorityBinding;
037import com.sun.identity.saml.assertion.Subject;
038import com.sun.identity.saml.assertion.SubjectLocality;
039import com.sun.identity.saml.common.SAMLConstants;
040import com.sun.identity.saml.common.SAMLException;
041import com.sun.identity.shared.DateUtils;
042import java.text.ParseException;
043import java.util.ArrayList;
044import java.util.Date;
045import java.util.Iterator;
046import java.util.List;
047import org.w3c.dom.Attr;
048import org.w3c.dom.Element;
049import org.w3c.dom.NamedNodeMap;
050import org.w3c.dom.Node;
051import org.w3c.dom.NodeList;
052
053/**
054 * The <code>FSAuthenticationStatement</code> element represents an
055 * authentication statement by the issuer that it's subject was authenticated
056 * by a  particular means at a particular time.
057 *
058 * @supported.all.api
059 */
060
061public class FSAuthenticationStatement extends AuthenticationStatement {
062    
063    protected Date reauthenticateOnOrAfter;
064    protected String sessionIndex = null;
065    protected AuthnContext _authnContext;
066    protected int minorVersion = IFSConstants.FF_11_PROTOCOL_MINOR_VERSION;
067    
068    /**
069     * Default Constructor.
070     */
071    public FSAuthenticationStatement(){
072    }
073    
074    /**
075     * Constructor to create <code>FSAuthenticationStatement</code> object.
076     *
077     * @param authMethod the Authentication method in the statement.
078     * @param authInstant the authentication date in the statement.
079     * @param subject the Subject in the statement.
080     * @param authnContext the Authentication Context.
081     * @throws FSMsgException if there is error
082     *         creating the object.
083     * @throws SAMLException if the version is incorrect.
084     */
085    public FSAuthenticationStatement(
086            String authMethod,
087            Date authInstant,
088            Subject subject,
089            AuthnContext authnContext
090            ) throws FSMsgException, SAMLException {
091        super(authMethod, authInstant, subject);
092        if (authnContext == null) {
093            if (FSUtils.debug.messageEnabled()) {
094                FSUtils.debug.message("FSAuthenticationStatement: missing" +
095                        "AuthnContext");
096            }
097        } else {
098            this._authnContext = authnContext;
099        }
100    }
101    
102    /**
103     * Constructor for create <code>FSAuthenticationStatement</code> object.
104     *
105     * @param authMethod the Authentication method in the statement.
106     * @param authInstant the authentication date in the statement.
107     * @param subject the <code>Subject</code> in the statement.
108     * @param subjectLocality the <code>SubjectLocality</code> in the statement.
109     * @param authorityBinding a List of <code>AuthorityBinding</code> objects.
110     * @param authnContext the Authentication Context.
111     * @throws FSMsgException if there is an error
112     *         creating the object.
113     * @throws SAMLException on error.
114     */
115    public FSAuthenticationStatement(
116            String authMethod,
117            Date authInstant,
118            Subject subject,
119            SubjectLocality subjectLocality,
120            List authorityBinding,
121            AuthnContext authnContext
122            ) throws FSMsgException, SAMLException {
123        super(authMethod,
124                authInstant,
125                subject,
126                subjectLocality,
127                authorityBinding);
128        
129        // check if the AuthnContext is null
130        if (authnContext == null) {
131            if (FSUtils.debug.messageEnabled()) {
132                FSUtils.debug.message("FSAuthenticationStatement: missing" +
133                        "AuthnContext.");
134            }
135        } else {
136            this._authnContext = authnContext;
137        }
138    }
139    
140    /**
141     * Constructs an <code>FSAuthenticationStatement</code> object from a
142     * Document Element.
143     *
144     * @param element the Document Element object.
145     * @throws FSMsgException if document element is null
146     *         or required attributes cannot be retrieved from the element.
147     * @throws SAMLException on error.
148     */
149    public FSAuthenticationStatement(Element element)
150    throws FSMsgException, SAMLException {
151        FSUtils.debug.message("FSAuthenticationStatement(Element):  Called");
152        if (element == null) {
153            FSUtils.debug.message("FSAuthenticationStatement: null input.");
154            throw new FSMsgException("nullInput",null);
155        }
156        int i = 0;
157        //handle the attributes of AuthenticationStatement
158        NamedNodeMap atts = ((Node)element).getAttributes();
159        int attCount = atts.getLength();
160        for (i = 0; i < attCount; i++) {
161            Node att = atts.item(i);
162            if (att.getNodeType() == Node.ATTRIBUTE_NODE) {
163                String attName = att.getLocalName();
164                if (attName == null || attName.length() == 0) {
165                    if (FSUtils.debug.messageEnabled()) {
166                        FSUtils.debug.message("FSAuthenticationStatement:" +
167                                "Attribute name is either null or empty.");
168                    }
169                    throw new FSMsgException("nullInput", null);
170                }
171                if (attName.equals(IFSConstants.AUTHENTICATION_METHOD)) {
172                    _authenticationMethod = ((Attr)att).getValue().trim();
173                } else if (attName.equals(IFSConstants.AUTHENTICATION_INSTANT)){
174                    try {
175                        _authenticationInstant =
176                                DateUtils.stringToDate(((Attr)att).getValue());
177                    } catch (ParseException pe ) {
178                        FSUtils.debug.error("FSAuthenticationStatement:" +
179                                "StringToDate: ", pe);
180                        throw new FSMsgException("wrongDateFormat",null);
181                    } // end of try...catch
182                } else if (attName.equals(IFSConstants.REAUTH_ON_OR_AFTER)) {
183                    try {
184                        reauthenticateOnOrAfter =
185                                DateUtils.stringToDate(((Attr)att).getValue());
186                    } catch (ParseException pe ) {
187                        FSUtils.debug.error("FSAuthenticationStatement:" +
188                                "StringToDate: ", pe);
189                        throw new FSMsgException("wrongDateFormat",null);
190                    }
191                } else if (attName.equals(IFSConstants.SESSION_INDEX)) {
192                    sessionIndex =
193                            ((Attr)att).getValue().trim();
194                }
195            }
196        } // end of for loop
197        //Handle the children elements of AuthenticationStatement
198        NodeList nodes = element.getChildNodes();
199        int nodeCount = nodes.getLength();
200        if (nodeCount > 0) {
201            for (i = 0; i < nodeCount; i++) {
202                Node currentNode = nodes.item(i);
203                if (currentNode.getNodeType() == Node.ELEMENT_NODE) {
204                    String tagName = currentNode.getLocalName();
205                    String tagNS = currentNode.getNamespaceURI();
206                    if ((tagName == null) || tagName.length() == 0 ||
207                            tagNS == null || tagNS.length() == 0) {
208                        if (FSUtils.debug.messageEnabled()) {
209                            FSUtils.debug.message("FSAuthenticationStatement: "+
210                                    "The  tag name or tag namespace of child" +
211                                    " element is either null or empty.");
212                        }
213                        throw new FSMsgException("nullInput",null);
214                    }
215                    if (tagName.equals(IFSConstants.AUTH_SUBJECT)) {
216                        if (this._subject != null) {
217                            if (FSUtils.debug.messageEnabled()) {
218                                FSUtils.debug.message(
219                                        "FSAuthenticationStatement" +
220                                        ":should only contain one subject");
221                            }
222                            throw new FSMsgException("oneElement",null);
223                        } else {
224                            this._subject =
225                                    new FSSubject((Element) currentNode);
226                        }
227                    } else if (tagName.equals(IFSConstants.SUBJECT_LOCALITY)) {
228                        if (_subjectLocality != null) {
229                            if (FSUtils.debug.messageEnabled()) {
230                                FSUtils.debug.message(
231                                        "FSAuthenticationStatement"+
232                                        "Statement: should at most " +
233                                        "contain one SubjectLocality.");
234                            }
235                            throw new FSMsgException("oneElement",null);
236                        } else {
237                            _subjectLocality =
238                                    new SubjectLocality((Element)currentNode);
239                        }
240                    } else if (tagName.equals(IFSConstants.AUTHN_CONTEXT) &&
241                            (tagNS.equals(
242                                    IFSConstants.libertyMessageNamespaceURI)||
243                            tagNS.equals(IFSConstants.FF_12_XML_NS))) {
244                        
245                        if (_authnContext != null) {
246                            if (FSUtils.debug.messageEnabled()) {
247                                FSUtils.debug.message("FSAuthentication"+
248                                        "Statement: should not contain more " +
249                                        "than  one AuthnContext element.");
250                            }
251                            throw new FSMsgException("oneElement",null);
252                        } else {
253                            _authnContext =
254                                    new AuthnContext((Element)currentNode);
255                        }
256                    } else if (tagName.equals(IFSConstants.AUTHORITY_BINDING)) {
257                        if (_authorityBinding == null) {
258                            _authorityBinding = new ArrayList();
259                        }
260                        if ((_authorityBinding.add(new AuthorityBinding(
261                                (Element)currentNode))) == false) {
262                            if (FSUtils.debug.messageEnabled()) {
263                                FSUtils.debug.message(
264                                        "FSAuthenticationStatement"+
265                                        ": failed to add to the" +
266                                        " AuthorityBinding list.");
267                            }
268                            throw new FSMsgException("addListError",null);
269                        }
270                    } else {
271                        if (FSUtils.debug.messageEnabled()) {
272                            FSUtils.debug.message("FSAuthenticationStatement:"+
273                                    "Wrong element "
274                                    + tagName + "included.");
275                        }
276                        throw new FSMsgException("wrongInput",null);
277                    }
278                } // end of if (currentNode.getNodeType() == Node.ELEMENT_NODE)
279            } // end of for loop
280        }  // end of if (nodeCount > 0)
281        // check if the subject is null
282        if (this._subject == null) {
283            if (FSUtils.debug.messageEnabled()) {
284                FSUtils.debug.message("FSAuthenticationStatement should " +
285                        "contain one subject.");
286            }
287            throw new FSMsgException("missingElement",null);
288        }
289        FSUtils.debug.message("FSAuthenticationStatement(Element): leaving");
290    }
291    
292    
293    /**
294     * Returns the value of <code>SessionIndex</code> attribute.
295     *
296     * @return the value of </code>SessionIndex</code> attribute.
297     * @see #setSessionIndex(String)
298     */
299    public String getSessionIndex(){
300        return sessionIndex;
301    }
302    
303    /**
304     * Sets the <code>SessionIndex</code> attribute.
305     *
306     * @param sessionIndex the value of <code>SessionIndex</code> attribute.
307     * @see #getSessionIndex
308     */
309    public void setSessionIndex(String sessionIndex){
310        this.sessionIndex = sessionIndex;
311    }
312    
313    /**
314     * Returns the re-authentication date for this
315     * authentication statement.
316     *
317     * @return the re-authentication date for this object.
318     * @see #setReauthenticateOnOrAfter
319     */
320    public Date getReauthenticateOnOrAfter(){
321        return reauthenticateOnOrAfter;
322    }
323    
324    /**
325     * Sets re-authentication date for this authentication
326     * statement.
327     *
328     * @param reauthenticateOnOrAfter the date object.
329     * @see #getReauthenticateOnOrAfter
330     */
331    public void setReauthenticateOnOrAfter(Date reauthenticateOnOrAfter){
332        this.reauthenticateOnOrAfter = reauthenticateOnOrAfter;
333    }
334    
335    /**
336     * Returns the Authentication Context in this
337     * authentication statement.
338     *
339     * @return the Authentication Context object.
340     * @see #setAuthnContext(AuthnContext)
341     */
342    public AuthnContext getAuthnContext(){
343        return _authnContext;
344    }
345    
346    /**
347     * Sets the Authentication Context object.
348     *
349     * @param authnContext the Authentication Context object.
350     * @see #getAuthnContext
351     */
352    public void setAuthnContext(AuthnContext authnContext){
353        this._authnContext = authnContext;
354    }
355    
356    /**
357     * Returns the value of <code>MinorVersion</code> attribute.
358     *
359     * @return the value of <code>MinorVersion</code> attribute.
360     * @see #setMinorVersion(int)
361     */
362    public int getMinorVersion() {
363        return minorVersion;
364    }
365    
366    /**
367     * Sets the value of <code>MinorVersion</code> attribute.
368     *
369     * @param version the <code>MinorVersion</code> attribute.
370     * @see #getMinorVersion
371     */
372    public void setMinorVersion(int version) {
373        minorVersion = version;
374    }
375    
376    /**
377     * Returns a String representation of this object.
378     *
379     * @throws FSMsgException if there is an error creating
380     *            the string.
381     * @return a String representation of this Object.
382     */
383    public String toXMLString() throws FSMsgException {
384        return (toXMLString(true, false));
385    }
386    
387    /**
388     * Returns a String representation of this object.
389     *
390     * @param includeNS Determines whether or not the namespace qualifier is
391     *                prepended to the Element when converted
392     * @param declareNS Determines whether or not the namespace is declared
393     *                within the Element.
394     * @return A string containing the valid XML for this object.
395     * @throws FSMsgException if there is an error creating
396     *         the string.
397     */
398    public String toXMLString(boolean includeNS,boolean declareNS)
399    throws FSMsgException {
400        StringBuffer result = new StringBuffer(1000);
401        String prefix = "";
402        String libprefix = "";
403        String uri = "";
404        String liburi = "";
405        if (includeNS) {
406            prefix = SAMLConstants.ASSERTION_PREFIX;
407            libprefix = IFSConstants.LIB_PREFIX;
408        }
409        if (declareNS) {
410            if (minorVersion == IFSConstants.FF_12_PROTOCOL_MINOR_VERSION) {
411                liburi = IFSConstants.LIB_12_NAMESPACE_STRING;
412            } else {
413                liburi = IFSConstants.LIB_NAMESPACE_STRING;
414            }
415            uri = SAMLConstants.assertionDeclareStr;
416        }
417        
418        result.append(IFSConstants.LEFT_ANGLE).append(prefix)
419        .append(IFSConstants.AUTHENTICATIONSTATEMENT)
420        .append(uri).append(IFSConstants.SPACE).append(liburi)
421        .append(IFSConstants.SPACE);
422        
423        if ((_authenticationMethod != null) &&
424                _authenticationMethod.length() != 0) {
425            result.append(IFSConstants.AUTHENTICATION_METHOD).append("=\"")
426            .append(_authenticationMethod).append("\" ");
427        }
428        
429        if (_authenticationInstant != null) {
430            result.append(IFSConstants.AUTHENTICATION_INSTANT).append("=\"")
431            .append(DateUtils.toUTCDateFormat(_authenticationInstant))
432            .append("\" ");
433        }
434        
435        if (reauthenticateOnOrAfter != null) {
436            result.append(IFSConstants.REAUTH_ON_OR_AFTER).append("=\"")
437            .append(DateUtils.toUTCDateFormat(reauthenticateOnOrAfter))
438            .append("\" ");
439        }
440        
441        if (sessionIndex != null) {
442            result.append(IFSConstants.SESSION_INDEX).append("=\"")
443            .append(sessionIndex).append("\" ");
444        }
445        
446        result.append("xsi:type")
447        .append("=\"")
448        .append(libprefix)
449        .append(IFSConstants.AUTHENTICATIONSTATEMENT_TYPE)
450        .append(IFSConstants.QUOTE)
451        .append(IFSConstants.RIGHT_ANGLE);
452        
453        if (getSubject() != null) {
454            result.append(
455                    ((FSSubject)getSubject()).toXMLString(includeNS, false));
456        }
457        
458        if (_subjectLocality != null) {
459            result.append(_subjectLocality.toString(includeNS, false));
460        }
461        
462        if ((_authorityBinding != null) && (!_authorityBinding.isEmpty())) {
463            Iterator iter = this.getAuthorityBinding().iterator();
464            while (iter.hasNext()) {
465                AuthorityBinding authBinding =
466                        (AuthorityBinding)iter.next();
467                result.append(authBinding.toString(includeNS, false));
468            }
469        }
470        if (_authnContext != null) {
471            result.append(_authnContext.toXMLString(includeNS, false));
472        }
473        result.append(IFSConstants.START_END_ELEMENT).append(prefix)
474        .append(IFSConstants.AUTHENTICATIONSTATEMENT)
475        .append(IFSConstants.RIGHT_ANGLE);
476        return(result.toString());
477    }
478}