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: SessionContext.java,v 1.2 2008/06/25 05:47:21 qcheng Exp $ 026 * 027 * Portions Copyrighted 2016 ForgeRock AS. 028 */ 029 030package com.sun.identity.liberty.ws.security; 031 032import static org.forgerock.openam.utils.Time.*; 033 034import com.sun.identity.shared.DateUtils; 035 036import com.sun.identity.federation.common.IFSConstants; 037import com.sun.identity.federation.message.common.AuthnContext; 038import com.sun.identity.federation.message.common.FSMsgException; 039 040import com.sun.identity.liberty.ws.common.wsse.WSSEConstants; 041 042import com.sun.identity.saml.common.SAMLConstants; 043import com.sun.identity.saml.common.SAMLException; 044import com.sun.identity.saml.common.SAMLRequesterException; 045import com.sun.identity.saml.common.SAMLUtils; 046 047import java.text.ParseException; 048 049import java.util.Date; 050 051import org.w3c.dom.Element; 052import org.w3c.dom.Node; 053import org.w3c.dom.NodeList; 054 055/** 056 * The <code>SessionContext</code> class represents session status of an entity 057 * to another system entity. It is supplied to a relying party to support policy 058 * enforcement. 059 * 060 * @supported.all.api 061 */ 062public class SessionContext { 063 064 protected SessionSubject _sessionSubject = null; 065 protected AuthnContext _authnContext = null; 066 protected String _providerID = null; 067 protected Date _issueInstant = null; 068 protected Date _authenticationInstant = null; 069 070 071 /** 072 * Default constructor 073 */ 074 protected SessionContext() { 075 } 076 077 /** 078 * Constructs a <code>SessionContext</code> object from a 079 * <code>SessionSubject</code> object, a <code>AuthnContext</code> 080 * object and a <code>String</code>. 081 * 082 * @param sessionSubject <code>SessionSubject</code> object. 083 * @param authnContext authentication context object. 084 * @param providerID provider ID. 085 * @throws SAMLException if <code>sessionSubject</code> is null or 086 * <code>providerID</code> is null. 087 */ 088 public SessionContext(SessionSubject sessionSubject, 089 AuthnContext authnContext, 090 String providerID) throws SAMLException { 091 if ((sessionSubject == null) || (providerID == null)) { 092 SAMLUtils.debug.message("SessionContext: null input."); 093 throw new SAMLRequesterException( 094 SAMLUtils.bundle.getString("nullInput")); 095 } 096 _sessionSubject = sessionSubject; 097 _authnContext = authnContext; 098 _providerID = providerID; 099 _issueInstant = newDate(); 100 _authenticationInstant = newDate(); 101 } 102 103 /** 104 * Returns the <code>SessionSubject</code> within the 105 * <code>SessionContext</code> object. 106 * 107 * @return <code>SessionSubject</code> object. 108 */ 109 public SessionSubject getSessionSubject() { 110 return _sessionSubject; 111 } 112 113 /** 114 * Sets the <code>SessionSubject</code> object. 115 * 116 * @param sub <code>SessionSubject</code> object. 117 */ 118 public void setSessionSubject(SessionSubject sub) { 119 _sessionSubject = sub; 120 } 121 122 /** 123 * Returns the <code>AuthnContext</code> within the 124 * <code>SessionContext</code> object. 125 * 126 * @return <code>AuthnContext</code> object. 127 */ 128 public AuthnContext getAuthnContext() { 129 return _authnContext; 130 } 131 132 /** 133 * Returns the <code>ProviderID</code> in the <code>SessionContext</code> 134 * object. 135 * 136 * @return <code>ProviderID</code> object 137 */ 138 public String getProviderID() { 139 return _providerID; 140 } 141 142 /** 143 * Sets the <code>AuthnContext</code> in the <code>SessionContext</code>. 144 * 145 * @param authnContext <code>AuthnContext</code> to be set. 146 * @return true if <code>AuthnContext</code> was set. 147 */ 148 public boolean setAuthnContext(AuthnContext authnContext) { 149 if (authnContext == null) { 150 if (SAMLUtils.debug.messageEnabled()) { 151 SAMLUtils.debug.message("SessionContext: " + 152 "setAuthnContext: Input is null."); 153 } 154 return false; 155 } 156 _authnContext = authnContext; 157 return true; 158 } 159 160 /** 161 * Constructs an <code>SessionContext</code> object from a DOM Element. 162 * 163 * @param element representing a DOM tree element. 164 * @throws SAMLException if there is an error in the sender or in the 165 * element definition. 166 */ 167 public SessionContext(Element element)throws SAMLException { 168 // make sure input is not null 169 if (element == null) { 170 SAMLUtils.debug.message("AttributeStatement: null input."); 171 throw new SAMLRequesterException( 172 SAMLUtils.bundle.getString("nullInput")); 173 } 174 175 // check if it's an ResourceAccessStatement 176 boolean valid = SAMLUtils.checkStatement(element, "SessionContext"); 177 if (!valid) { 178 SAMLUtils.debug.message("SessionContext: Wrong input."); 179 throw new SAMLRequesterException( 180 SAMLUtils.bundle.getString("wrongInput")); 181 } 182 183 String authInstant = element.getAttribute("AuthenticationInstant"); 184 String issueInstant = element.getAttribute("AssertionIssueInstant"); 185 if ((authInstant == null) || (issueInstant == null)) { 186 SAMLUtils.debug.message("SessionContext: AuthenticationInstant " + 187 "or AssertionIssueInstant is missing!"); 188 throw new SAMLRequesterException( 189 SAMLUtils.bundle.getString("nullInput")); 190 } 191 try { 192 _issueInstant = DateUtils.stringToDate(issueInstant); 193 _authenticationInstant = DateUtils.stringToDate(authInstant); 194 } catch (ParseException e) { 195 //TODO: handle exception 196 } 197 198 //Handle the children elements of SessionContext 199 NodeList nodes = element.getChildNodes(); 200 int nodeCount = nodes.getLength(); 201 if (nodeCount > 0) { 202 for (int i = 0; i < nodeCount; i++) { 203 Node currentNode = nodes.item(i); 204 if (currentNode.getNodeType() == Node.ELEMENT_NODE) { 205 String tagName = currentNode.getLocalName(); 206 String tagNS = currentNode.getNamespaceURI(); 207 if ((tagName == null) || tagName.length() == 0 || 208 tagNS == null || tagNS.length() == 0) { 209 if (SAMLUtils.debug.messageEnabled()) { 210 SAMLUtils.debug.message("SessionContext: The tag name"+ 211 " or tag namespace of child element is" + 212 " either null or empty."); 213 } 214 throw new SAMLRequesterException( 215 SAMLUtils.bundle.getString("nullInput")); 216 } 217 if (tagName.equals("SessionSubject") && 218 tagNS.equals("urn:liberty:sec:2003-08")) { //sec: 219 if (_sessionSubject != null) { 220 if (SAMLUtils.debug.messageEnabled()) { 221 SAMLUtils.debug.message("SessionContext:" + 222 " should only contain one SessionSubject"); 223 } 224 throw new SAMLRequesterException( 225 SAMLUtils.bundle.getString("oneElement")); 226 } else { 227 try { 228 _sessionSubject = 229 new SessionSubject((Element) currentNode); 230 } catch (Exception e) { 231 if (SAMLUtils.debug.messageEnabled()) { 232 SAMLUtils.debug.message("SessionContext:" + 233 "could not new SessionSubject" + 234 " object."); 235 } 236 throw new SAMLRequesterException( 237 SAMLUtils.bundle.getString( 238 "SessionSubject")); 239 } 240 } 241 } else if (tagName.equals("ProviderID") && 242 tagNS.equals("urn:liberty:sec:2003-08")) { //sec 243 if (_providerID != null) { 244 if (SAMLUtils.debug.messageEnabled()) { 245 SAMLUtils.debug.message("SessionContext:"+ 246 " should at most contain one" + 247 " ProviderID."); 248 } 249 throw new SAMLRequesterException( 250 SAMLUtils.bundle.getString("oneElement")); 251 } else { 252 _providerID = currentNode.getChildNodes().item(0) 253 .getNodeValue(); 254 } 255 } else if (tagName.equals("AuthnContext") && 256 tagNS.equals("urn:liberty:iff:2003-08")) { //lib 257 if (_authnContext != null) { 258 if (SAMLUtils.debug.messageEnabled()) { 259 SAMLUtils.debug.message("SessionContext: " + 260 "should at most contain one " + 261 "AuthnContext"); 262 } 263 throw new SAMLRequesterException( 264 SAMLUtils.bundle.getString("oneElement")); 265 } else { 266 try { 267 _authnContext = new AuthnContext((Element) 268 currentNode); 269 } catch (Exception e) { 270 if (SAMLUtils.debug.messageEnabled()) { 271 SAMLUtils.debug.message("SessionContext:" + 272 "could not new AuthnContext" + 273 " object.", e); 274 } 275 throw new SAMLRequesterException( 276 SAMLUtils.bundle.getString( 277 "AuthnContext")); 278 } 279 } 280 } else { 281 if (SAMLUtils.debug.messageEnabled()) { 282 SAMLUtils.debug.message("SessionContext: "+ 283 "Wrong element " + tagName + " included."); 284 } 285 throw new SAMLRequesterException( 286 SAMLUtils.bundle.getString("wrongInput")); 287 } 288 } // end of if (currentNode.getNodeType() == Node.ELEMENT_NODE) 289 } // end of for loop 290 } // end of if (nodeCount > 0) 291 // check if the subject is null 292 if ((_sessionSubject == null)||(_authnContext == null)) { 293 if (SAMLUtils.debug.messageEnabled()) { 294 SAMLUtils.debug.message("SessionContext should contain " + 295 "one SessionSubject and one " + 296 " one AuthnContext."); 297 } 298 throw new SAMLRequesterException( 299 SAMLUtils.bundle.getString("missingElement")); 300 } 301 302 } 303 304 /** 305 * Returns a String representation of the <code>SessionContext</code> 306 * element. 307 * 308 * @return A string containing the valid XML for this element. 309 * By default name space name is prepended to the element name 310 * example <code><saml:Subject></code>. 311 * @throws ParseException if could not convert String Date 312 * expression to Date object. 313 * @throws FSMsgException if could not get <code>AuthnContext</code> XML 314 * String representation. 315 */ 316 public String toXMLString() throws ParseException, FSMsgException { 317 return toXMLString(true, false); 318 } 319 320 /** 321 * Returns a String representation of the <code><SessionContext></code> 322 * element. 323 * 324 * @param includeNS if true prepends all elements by their Namespace 325 * name <code><saml:Subject></code>. 326 * @param declareNS if true includes the namespace within the 327 * generated XML. 328 * @return A string containing the valid XML for this element. Return null 329 * if error happened. 330 * @throws ParseException if could not convert String Date 331 * expression to Date object. 332 * @throws FSMsgException if could not get <code>AuthnContext</code> XML 333 * String representation. 334 **/ 335 public String toXMLString(boolean includeNS, boolean declareNS) 336 throws ParseException, FSMsgException { 337 338 SAMLConstants sc; 339 StringBuffer xml = new StringBuffer(3000); 340 String secprefix = ""; 341 String libprefix = ""; 342 String liburi = ""; 343 String secNS = ""; 344 345 if (includeNS) { 346 libprefix = IFSConstants.LIB_PREFIX; 347 secprefix = WSSEConstants.TAG_SEC + ":"; 348 } 349 if (declareNS) { 350 liburi = IFSConstants.LIB_NAMESPACE_STRING; 351 secNS = " " + WSSEConstants.TAG_XMLNS + ":" + 352 WSSEConstants.TAG_SEC + "=\"" + WSSEConstants.NS_SEC + 353 "\""; 354 } 355 356 xml.append("<").append(secprefix). 357 append(WSSEConstants.TAG_SESSIONCONTEXT).append(secNS).append(" "). 358 append("AuthenticationInstant=").append("\""). 359 append(DateUtils.toUTCDateFormat(_issueInstant)).append("\" "). 360 append("AssertionIssueInstant=").append("\""). 361 append(DateUtils.toUTCDateFormat(_authenticationInstant)). 362 append("\""). 363 append(">"); 364 365 xml.append(_sessionSubject.toXMLString(includeNS, declareNS)); 366 367 xml.append("<").append(secprefix).append(WSSEConstants.TAG_PROVIDERID). 368 append(">").append(_providerID).append("</").append(secprefix). 369 append(WSSEConstants.TAG_PROVIDERID).append(">"); 370 371 if (_authnContext != null) { 372 xml.append(_authnContext.toXMLString(includeNS, declareNS)); 373 } 374 375 xml.append("</").append(secprefix). 376 append(WSSEConstants.TAG_SESSIONCONTEXT).append(">"); 377 378 return xml.toString(); 379 } 380} 381