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: SecurityAssertion.java,v 1.3 2009/10/01 18:42:07 mallas Exp $ 026 * 027 */ 028 029package com.sun.identity.liberty.ws.security; 030 031 032import com.sun.identity.shared.xml.XMLUtils; 033import com.sun.identity.shared.DateUtils; 034import com.sun.identity.liberty.ws.common.wsse.WSSEConstants; 035import com.sun.identity.liberty.ws.soapbinding.SOAPBindingConstants; 036import com.sun.identity.saml.assertion.Advice; 037import com.sun.identity.saml.assertion.Assertion; 038import com.sun.identity.saml.assertion.Conditions; 039import com.sun.identity.saml.assertion.Statement; 040import com.sun.identity.saml.assertion.Subject; 041import com.sun.identity.saml.assertion.SubjectConfirmation; 042import com.sun.identity.saml.assertion.SubjectStatement; 043 044import com.sun.identity.saml.common.SAMLConstants; 045import com.sun.identity.saml.common.SAMLException; 046import com.sun.identity.saml.common.SAMLUtils; 047 048import com.sun.identity.saml.xmlsig.XMLSignatureManager; 049 050import java.io.ByteArrayOutputStream; 051 052import java.text.ParseException; 053 054import java.util.Collections; 055import java.util.Date; 056import java.util.HashSet; 057import java.util.Iterator; 058import java.util.List; 059import java.util.Map; 060import java.util.Set; 061 062import org.w3c.dom.Attr; 063import org.w3c.dom.Document; 064import org.w3c.dom.Element; 065import org.w3c.dom.NamedNodeMap; 066import org.w3c.dom.Node; 067import org.w3c.dom.NodeList; 068 069/** 070 * The <code>SecurityAssertion</code> class provides an extension to 071 * <code>Assertion</code> class to support <code>ID-WSF</code> 072 * <code>ResourceAccessStatement</code> and 073 * <code>SessionContextStatement</code>. 074 * 075 * @supported.all.api 076 */ 077public class SecurityAssertion extends Assertion { 078 079 private String verifyingCertAlias = null; 080 081 /** 082 * This constructor creates a <code>SecurityAssertion</code> object 083 * from a DOM Element. 084 * 085 * @param assertionElement A <code>org.w3c.dom.Element</code> representing 086 * DOM tree for <code>Assertion</code> object 087 * @throws SAMLException if it could not process the Element properly, 088 * implying that there is an error in the sender or in the 089 * element definition. 090 */ 091 public SecurityAssertion(org.w3c.dom.Element assertionElement) 092 throws SAMLException { 093 parseAssertionElement(assertionElement); 094 } 095 096 /** 097 * Constructs <code>SecurityAssertion</code> object with the 098 * <code>assertionID</code>, the issuer, time when assertion issued 099 * and a <code>Set</code> of <code>Statement</code>(s) in the assertion. 100 * 101 * @param assertionID <code>assertionID</code> attribute contained within 102 * this <code>Assertion</code> if null, an <code>assertionID</code> 103 * is generated internally. 104 * @param issuer String representing the issuer of this assertion. 105 * @param issueInstant time instant of the issue. It has type 106 * <code>dateTime</code> which is built in to the W3C XML Schema 107 * Types specification.if null, current time is used. 108 * @param statements Set of <code>Statement</code> objects within this 109 * <code>Assertion</code>. It could be of type 110 * <code>AuthenticationStatement</code>, 111 * <code>AuthorizationDecisionStatement</code> and 112 * <code>AttributeStatement</code>. Each Assertion can have multiple 113 * type of statements in it. 114 * @throws SAMLException issuer is null or the size of statements is 0. 115 */ 116 public SecurityAssertion(String assertionID,java.lang.String issuer, 117 Date issueInstant, Set statements) throws SAMLException { 118 super(assertionID, issuer, issueInstant, statements); 119 } 120 121 /** 122 * Constructs <code>SecurityAssertion</code> object with the 123 * <code>assertionID</code>, the issuer, time when assertion issued, the 124 * conditions when creating a new assertion and a <code>Set</code> of 125 * <code>Statement</code>(s) in the assertion. 126 * 127 * @param assertionID String representing <code>AssertionID</code> 128 * contained within this <code>Assertion</code> if null its generated 129 * internally. 130 * @param issuer String representing the issuer of this assertion. 131 * @param issueInstant time instant of the issue. It has type 132 * <code>dateTime</code> which is built in to the W3C XML 133 * Schema Types specification. if null current time is used. 134 * @param conditions <code>Conditions</code> under which the this 135 * <code>Assertion</code> is valid. 136 * @param statements Set of <code>Statement</code> objects within this 137 * <code>Assertion</code>. It could be of type 138 * <code>AuthenticationStatement</code>, 139 * <code>AuthorizationDecisionStatement</code> and 140 * <code>AttributeStatement</code>. Each Assertion can have multiple 141 * type of statements in it. 142 * @throws SAMLException issuer is null or the size of statements is 0. 143 */ 144 public SecurityAssertion(String assertionID,java.lang.String issuer, 145 Date issueInstant, Conditions conditions, Set statements) 146 throws SAMLException { 147 super(assertionID, issuer, issueInstant, conditions, statements); 148 } 149 150 /** 151 * Constructs <code>SecurityAssertion</code> object with the 152 * <code>assertionID</code>, the issuer, time when assertion issued, 153 * the conditions when creating a new assertion, <code>Advice</code> 154 * applicable to this <code>Assertion</code> and a <code>Set</code> of 155 * <code>Statement</code>(s) in the assertion. 156 * 157 * @param assertionID <code>AssertionID</code> object contained within this 158 * <code>Assertion</code> if null its generated internally. 159 * @param issuer String representing the issuer of this assertion. 160 * @param issueInstant time instant of the issue. It has type 161 * <code>dateTime</code> which is built in to the W3C XML Schema 162 * Types specification. if null current time is used. 163 * @param conditions <code>Conditions</code> under which the this 164 * <code>Assertion</code> is valid. 165 * @param advice <code>Advice</code> applicable for this 166 * <code>Assertion</code>. 167 * @param statements Set of <code>Statement</code> objects within this 168 * <code>Assertion</code>. It could be of type 169 * <code>AuthenticationStatement</code>, 170 * <code>AuthorizationDecisionStatement</code> and 171 * <code>AttributeStatement</code>. Each Assertion can have multiple 172 * type of statements in it. 173 * @throws SAMLException issuer is null or the size of statements is 0. 174 */ 175 public SecurityAssertion(String assertionID,java.lang.String issuer, 176 Date issueInstant, Conditions conditions, Advice advice, 177 Set statements) throws SAMLException { 178 super(assertionID, issuer, issueInstant, conditions, 179 advice, statements); 180 } 181 182 /** 183 * Sets the value of the certificate alias. 184 * 185 * @param certAlias the certificate alias. 186 */ 187 public void setVerifyingCertAlias(String certAlias) { 188 verifyingCertAlias = certAlias; 189 } 190 191 /** 192 * Return whether the signature is valid. 193 * 194 * @return true if the signature is valid. 195 */ 196 public boolean isSignatureValid() { 197 if (signed & ! validationDone) { 198 try { 199 XMLSignatureManager manager = XMLSignatureManager.getInstance(); 200 valid = manager.verifyXMLSignature(xmlString, 201 ASSERTION_ID_ATTRIBUTE, verifyingCertAlias); 202 } catch (Exception e) { 203 if (SAMLUtils.debug.warningEnabled()) { 204 SAMLUtils.debug.warning( 205 "SecurityAssertion.isSignatureValid: "+ 206 " signature validation exception", e); 207 } 208 valid = false; 209 } 210 if (SAMLUtils.debug.messageEnabled()) { 211 SAMLUtils.debug.message("SAMLUtils.checkSignatureValid:"+ 212 " valid = " + valid); 213 } 214 215 validationDone = true; 216 } 217 return valid; 218 } 219 220 /** 221 * Determines if the <code>SecurityAssertion</code> contains SAML Bearer 222 * confirmation method. 223 * 224 * @return true if the <code>SecurityAssertion</code> contains SAML Bearer 225 * confirmation. 226 */ 227 public boolean isBearer() { 228 if (_statements == null || _statements.isEmpty()) { 229 return false; 230 } 231 232 Iterator iter = _statements.iterator(); 233 while(iter.hasNext()) { 234 Object statement = iter.next(); 235 if (!(statement instanceof SubjectStatement)) { 236 continue; 237 } 238 Subject subject = ((SubjectStatement)statement).getSubject(); 239 if (subject == null) { 240 continue; 241 } 242 SubjectConfirmation sc = subject.getSubjectConfirmation(); 243 if (sc == null) { 244 continue; 245 } 246 Set confirmationMethods = sc.getConfirmationMethod(); 247 if (confirmationMethods == null || confirmationMethods.isEmpty()) { 248 continue; 249 } 250 if (confirmationMethods.contains( 251 SAMLConstants.CONFIRMATION_METHOD_BEARER)) { 252 return true; 253 } 254 } 255 return false; 256 } 257 258 /** 259 * Determines if the <code>SecurityAssertion</code> contains SAML Bearer 260 * confirmation method. If it is, return its Subject. Otherwise, return 261 * null. 262 * 263 * @return Subject if the <code>SecurityAssertion</code> contains SAML 264 * Bearer confirmation. 265 */ 266 public Subject getBearerSubject() { 267 if (_statements == null || _statements.isEmpty()) { 268 return null; 269 } 270 271 Iterator iter = _statements.iterator(); 272 while(iter.hasNext()) { 273 Object statement = iter.next(); 274 if (!(statement instanceof SubjectStatement)) { 275 continue; 276 } 277 Subject subject = ((SubjectStatement)statement).getSubject(); 278 if (subject == null) { 279 continue; 280 } 281 SubjectConfirmation sc = subject.getSubjectConfirmation(); 282 if (sc == null) { 283 continue; 284 } 285 Set confirmationMethods = sc.getConfirmationMethod(); 286 if (confirmationMethods == null || confirmationMethods.isEmpty()) { 287 continue; 288 } 289 if (confirmationMethods.contains( 290 SAMLConstants.CONFIRMATION_METHOD_BEARER)) { 291 return subject; 292 } 293 } 294 return null; 295 } 296 297 /** 298 * Create a String representation of the element. 299 * @return A string containing the valid XML for this element. 300 * By default name space name is prepended to the element name 301 * example <code><saml:Assertion></code>. 302 * 303 * @return the String representation of this element. 304 */ 305 public java.lang.String toString() { 306 // call toString() with includeNS true by default and declareNS false 307 return this.toString(true, false); 308 } 309 310 /** 311 * Creates a String representation of the <code><Assertion></code> 312 * element. 313 * 314 * @param includeNS if true prepends all elements by their Namespace 315 * name example <code><saml:Assertion></code>; 316 * @param declareNS if true includes the namespace within the generated 317 * XML. 318 * @return A string containing the valid XML for this element. 319 */ 320 public java.lang.String toString(boolean includeNS, boolean declareNS) { 321 if (signed && (xmlString != null)) { 322 return xmlString; 323 } 324 325 StringBuffer xml = new StringBuffer(3000); 326 String NS=""; 327 String appendNS=""; 328 if (declareNS) { 329 NS=SAMLConstants.assertionDeclareStr; 330 } 331 if (includeNS) { 332 appendNS="saml:"; 333 } 334 String dateStr = null; 335 336 if (_issueInstant != null) { 337 dateStr = DateUtils.toUTCDateFormat(_issueInstant); 338 } 339 340 xml.append("<").append(appendNS).append("Assertion").append(" "). 341 append(NS).append(" ").append("MajorVersion").append("=\""). 342 append(_majorVersion).append("\"").append(" "). 343 append("MinorVersion").append("=\"").append(_minorVersion). 344 append("\"").append(" ").append("AssertionID=\""). 345 append(_assertionID.getAssertionIDReference()).append("\""). 346 append(" ").append("Issuer").append("=\"").append(_issuer). 347 append("\"").append(" ").append("IssueInstant").append("=\""). 348 append(dateStr).append("\""). 349 append(" ").append(">").append(sc.NL); 350 if (_conditions != null) { 351 xml.append(_conditions.toString(includeNS, false)); 352 } 353 if (_advice != null) { 354 xml.append(_advice.toString(includeNS, false)); 355 } 356 Iterator i = getStatement().iterator(); 357 while (i.hasNext()) { 358 Statement st = (Statement)i.next(); 359 xml.append(st.toString(includeNS, declareNS)); 360 } 361 if (signed && (signatureString != null)) { 362 xml.append(signatureString); 363 } 364 String o = SAMLUtils.makeEndElementTagXML("Assertion", includeNS); 365 xml.append(o); 366 return xml.toString(); 367 } 368 369 protected boolean processUnknownElement(Element element) 370 throws SAMLException { 371 if (super.processUnknownElement(element)) { 372 if (SAMLUtils.debug.messageEnabled()) { 373 SAMLUtils.debug.message( 374 "SecurityAssertion.processUnknownElement: " + 375 "super returns true"); 376 } 377 return true; 378 } 379 380 if (SAMLUtils.debug.messageEnabled()) { 381 SAMLUtils.debug.message( 382 "SecurityAssertion.processUnknownElement: " + 383 "super returns false"); 384 } 385 String localName = element.getLocalName(); 386 if (localName.equals("ResourceAccessStatement")) { 387 _statements.add(new ResourceAccessStatement(element)); 388 return true; 389 } 390 391 if (localName.equals("SessionContextStatement")) { 392 _statements.add(new SessionContextStatement(element)); 393 return true; 394 } 395 396 return false; 397 } 398 399 protected int getMinAssertionMinorVersion() { 400 return sc.ASSERTION_MINOR_VERSION; 401 } 402 403 protected int getMaxAssertionMinorVersion() { 404 return sc.ASSERTION_MINOR_VERSION; 405 } 406 407 /** 408 * Add the <code>Assertion</code> to the Document Element. 409 * 410 * @param headerE the element to be updated. 411 * @throws Exception if there is an error. 412 */ 413 public void addToParent(Element headerE) throws Exception { 414 415 Document doc = headerE.getOwnerDocument(); 416 417 Element securityE = 418 doc.createElementNS(WSSEConstants.NS_WSSE_WSF11, 419 WSSEConstants.TAG_WSSE + ":" + 420 WSSEConstants.TAG_SECURITYT); 421 422 securityE.setAttributeNS(SOAPBindingConstants.NS_XML, 423 WSSEConstants.TAG_XML_WSSE, 424 WSSEConstants.NS_WSSE_WSF11); 425 426 headerE.appendChild(securityE); 427 428 Document assertionDoc = XMLUtils.toDOMDocument( 429 toString(true, true), SAMLUtils.debug); 430 431 Element assertionE = assertionDoc.getDocumentElement(); 432 securityE.appendChild(doc.importNode(assertionE, true)); 433 434 } 435}
Copyright © 2010-2017, ForgeRock All Rights Reserved.