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: SubjectConfirmation.java,v 1.2 2008/06/25 05:47:33 qcheng Exp $ 026 * 027 */ 028 029package com.sun.identity.saml.assertion; 030 031import com.sun.identity.saml.common.SAMLException; 032import com.sun.identity.saml.common.SAMLUtilsCommon; 033import com.sun.identity.saml.common.SAMLRequesterException; 034import com.sun.identity.saml.common.SAMLConstants; 035import com.sun.identity.shared.xml.XMLUtils; 036import org.w3c.dom.Element; 037import org.w3c.dom.Node; 038import org.w3c.dom.NodeList; 039import java.util.Set; 040import java.util.Iterator; 041import java.util.Collections; 042import java.util.HashSet; 043 044/** 045 *The <code>SubjectConfirmation</code> element specifies a subject by specifying 046 *data that authenticates the subject. 047 *@supported.all.api 048 */ 049public class SubjectConfirmation { 050 static SAMLConstants sc; 051 private Set _confirmationMethodList = 052 Collections.synchronizedSet(new HashSet()); 053 private Element _subjectConfirmationData=null; 054 private Element _keyInfo=null; 055 056 /** 057 * Constructs a subject confirmation element from an existing 058 * XML block. 059 * 060 * @param subjectConfirmationElement a DOM Element representing the 061 * <code>SubjectConfirmation</code> object. 062 * @throws SAMLException 063 */ 064 public SubjectConfirmation(org.w3c.dom.Element subjectConfirmationElement) 065 throws SAMLException 066 { 067 Element elt = (Element) subjectConfirmationElement; 068 String eltName = elt.getLocalName(); 069 if (eltName == null) { 070 if (SAMLUtilsCommon.debug.messageEnabled()) { 071 SAMLUtilsCommon.debug.message("SubjectConfirmation: local name " 072 + "missing"); 073 } 074 throw new SAMLRequesterException(SAMLUtilsCommon.bundle.getString 075 ("nullInput")) ; 076 } 077 if (!(eltName.equals("SubjectConfirmation"))) { 078 if (SAMLUtilsCommon.debug.messageEnabled()) { 079 SAMLUtilsCommon.debug.message("SubjectConfirmation: "+ 080 "invalid root element"); 081 } 082 throw new SAMLRequesterException(SAMLUtilsCommon.bundle.getString( 083 "invalidElement")) ; 084 } 085 // TODO: Not checking for the sequence of elements 086 NodeList nl = elt.getChildNodes(); 087 int length = nl.getLength(); 088 for (int n=0; n<length; n++) { 089 Node child = (Node)nl.item(n); 090 if (child.getNodeType() != Node.ELEMENT_NODE) { 091 continue; 092 } 093 String childName = child.getLocalName(); 094 if (childName.equals("ConfirmationMethod")) { 095 _confirmationMethodList.add( 096 XMLUtils.getElementValue((Element) child)); 097 } 098 else if (childName.equals("SubjectConfirmationData")) { 099 if (_subjectConfirmationData != null) { 100 // this is the seconf time this is passed so flag error 101 if (SAMLUtilsCommon.debug.messageEnabled()) { 102 SAMLUtilsCommon.debug.message("SubjectConfirmation: " 103 + "SubjectConfirmationData already parsed"); 104 } 105 throw new SAMLRequesterException( 106 SAMLUtilsCommon.bundle.getString("moreElement")); 107 } 108 _subjectConfirmationData = (Element) child; 109 } 110 else if (childName.equals("KeyInfo")) { 111 if (_keyInfo != null) { 112 if (SAMLUtilsCommon.debug.messageEnabled()) { 113 SAMLUtilsCommon.debug.message("SubjectConfirmation: " 114 + "KeyInfo already parsed"); 115 } 116 throw new SAMLRequesterException( 117 SAMLUtilsCommon.bundle.getString("moreElement")); 118 } 119 _keyInfo = (Element) child; 120 } else { 121 if (SAMLUtilsCommon.debug.messageEnabled()) 122 SAMLUtilsCommon.debug.message("SubjectConfirmation: " + 123 "unsupported element KeyInfo in SubjectConfirmation"); 124 throw new SAMLRequesterException( 125 SAMLUtilsCommon.bundle.getString("unsupportedElement")); 126 } 127 } 128 129 if (_confirmationMethodList.isEmpty()) { 130 if (SAMLUtilsCommon.debug.messageEnabled()) 131 SAMLUtilsCommon.debug.message("SubjectConfirmation: Mandatory " 132 + "element confirmation method missing"); 133 throw new SAMLRequesterException(SAMLUtilsCommon.bundle.getString( 134 "missingElement")); 135 } 136 } 137 138 /** 139 * Constructor with a single confirmation method. 140 * 141 * @param confirmationMethod A URI (String) that identifies a protocol used 142 * to authenticate a <code>Subject</code>. Please refer to 143 * <code>draft-sstc-core-25</code> Section 7 for a list of URIs 144 * identifying common authentication protocols. 145 * @exception SAMLException if the input data is null. 146 */ 147 public SubjectConfirmation(java.lang.String confirmationMethod) 148 throws SAMLException 149 { 150 if ((confirmationMethod == null) || 151 (confirmationMethod.length() == 0)) { 152 if (SAMLUtilsCommon.debug.messageEnabled()) { 153 SAMLUtilsCommon.debug.message("SubjectConfirmation: null " 154 + "confirmationMethod specified"); 155 } 156 throw new SAMLRequesterException(SAMLUtilsCommon.bundle.getString( 157 "nullInput")) ; 158 } 159 _confirmationMethodList.add(confirmationMethod); 160 } 161 162 /** 163 * Constructor for multiple confirmation methods 164 * @param confirmationMethods a <code>Set</code> of 165 * <code>confirmationMethods</code> 166 * @exception SAMLException if the <code>confirmationMethods</code> is 167 * empty. 168 */ 169 public SubjectConfirmation(Set confirmationMethods) throws SAMLException { 170 if (confirmationMethods.isEmpty()) { 171 if (SAMLUtilsCommon.debug.messageEnabled()) { 172 SAMLUtilsCommon.debug.message("SubjectConfirmation: No " 173 + "confirmationMethods in the Set"); 174 } 175 throw new SAMLRequesterException(SAMLUtilsCommon.bundle.getString( 176 "nullInput")) ; 177 } 178 _confirmationMethodList.addAll(confirmationMethods); 179 } 180 181 /** 182 * Adds a <code>confirmationMethod</code> to this 183 * <code>SubjectConfirmation</code> element. 184 * 185 * @param confirmationMethod a String which is a URI (String) that 186 * identifies a protocol used to authenticate a <code>Subject</code>. 187 * @return true indicating success of the operation. 188 */ 189 public boolean addConfirmationMethod(String confirmationMethod) { 190 if ((confirmationMethod == null) || 191 (confirmationMethod.length() == 0)) { 192 return false; 193 } 194 _confirmationMethodList.add(confirmationMethod); 195 return true; 196 } 197 198 /** 199 * Constructs an <code>SubjectConfirmation</code> instance. 200 * 201 * @param confirmationMethods A set of <code>confirmationMethods</code> 202 * each of which is a URI (String) that identifies a protocol 203 * used to authenticate a <code>Subject</code>. Please refer to 204 * <code>draft-sstc-core-25</code> Section 7 for 205 * a list of URIs identifying common authentication protocols. 206 * @param subjectConfirmationData Additional authentication information to 207 * be used by a specific authentication protocol. Can be passed as 208 * null if there is no <code>subjectConfirmationData</code> for the 209 * <code>SubjectConfirmation</code> object. 210 * @param keyInfo An XML signature element that specifies a cryptographic 211 * key held by the <code>Subject</code>. 212 * @exception SAMLException if the input data is invalid or 213 * <code>confirmationMethods</code> is empty. 214 */ 215 public SubjectConfirmation(Set confirmationMethods, 216 Element subjectConfirmationData, 217 Element keyInfo) throws SAMLException 218 { 219 if (confirmationMethods.isEmpty()) { 220 if (SAMLUtilsCommon.debug.messageEnabled()) { 221 SAMLUtilsCommon.debug.message("SubjectConfirmation: No " 222 + "confirmationMethods in the Set"); 223 } 224 throw new SAMLRequesterException(SAMLUtilsCommon.bundle.getString( 225 "nullInput")) ; 226 } 227 _confirmationMethodList.addAll(confirmationMethods); 228 _subjectConfirmationData = subjectConfirmationData; 229 _keyInfo = keyInfo; 230 } 231 232 /** 233 *Gets Confirmation Method(s) 234 *@return A <code>java.util.Set</code> of confirmation Methods. Each method 235 *contained within is a <code>String</code> representing the confirmation 236 * method. 237 */ 238 public Set getConfirmationMethod() { 239 return _confirmationMethodList; 240 } 241 242 /** 243 *Get Subject Confirmation Data 244 *@return A String representation of the subject confirmation data with the 245 *Subject Confirmation element 246 */ 247 public Element getSubjectConfirmationData() { 248 return _subjectConfirmationData; 249 } 250 251 /** 252 * Sets the <code>SubjectConfirmationData</code> 253 * 254 * @param subjectConfirmationData A String representation of the subject 255 * confirmation data within this <code>SubjectConfirmation</code> 256 * element 257 * @return true indicating success of the operation. 258 */ 259 public boolean setSubjectConfirmationData( 260 Element subjectConfirmationData) 261 { 262 if (subjectConfirmationData == null) { 263 return false; 264 } 265 _subjectConfirmationData = subjectConfirmationData; 266 return true; 267 } 268 269 /** 270 * Sets the <code>SubjectConfirmationData</code>. 271 * 272 * @param scDataString A String representation of the subject 273 * confirmation data within this <code>SubjectConfirmation</code> 274 * element. 275 * @return true if the operation succeed. 276 */ 277 public boolean setSubjectConfirmationData(String scDataString) { 278 if (scDataString == null) { 279 return false; 280 } 281 StringBuffer sb = new StringBuffer(300); 282 sb.append(SAMLUtilsCommon.makeStartElementTagXML( 283 "SubjectConfirmationData", true, true)). 284 append(scDataString). 285 append(SAMLUtilsCommon.makeEndElementTagXML( 286 "SubjectConfirmationData", true)); 287 try { 288 _subjectConfirmationData = XMLUtils.toDOMDocument( 289 sb.toString().trim(), 290 SAMLUtilsCommon.debug).getDocumentElement(); 291 } catch (Exception e) { 292 if (SAMLUtilsCommon.debug.messageEnabled()) { 293 SAMLUtilsCommon.debug.message("SubjectConfirmation: " + 294 "exception when setting scDataString.", e); 295 } 296 return false; 297 } 298 return true; 299 } 300 301 /** 302 * Returns the key info. 303 * 304 * @return The key info. 305 */ 306 public Element getKeyInfo() { 307 return _keyInfo; 308 } 309 310 /** 311 * Sets the key info. 312 * 313 * @param keyInfo <code>dsig.KeyInfo</code>. 314 * @return true if operations succeeds. 315 */ 316 public boolean setKeyInfo(Element keyInfo) { 317 if (keyInfo != null) { 318 _keyInfo = keyInfo; 319 return true; 320 } else { 321 return false; 322 } 323 } 324 325 /** 326 * Checks for equality between this object and the 327 * <code>SubjectConfirmation</code> passed down as parameter. Checks to 328 * see that each have confirmations method present in the other one (does 329 * not care about sequence) 330 * Also does an exact match on <code>SubjectConfirmationData</code>. 331 * Note: no check is done for <code>KeyInfo</code>. 332 * 333 * @param subjectConfirmation <code>SubjectConfirmation</code> to be 334 * checked. 335 * @return true if the two are EXACTLY equal. 336 */ 337 public boolean equals(SubjectConfirmation subjectConfirmation) { 338 boolean cmEqual = true; 339 boolean scDataEqual = true; 340 if (subjectConfirmation != null) { 341 Set confMethods = subjectConfirmation.getConfirmationMethod(); 342 int passedSize = confMethods.size(); 343 if (passedSize != _confirmationMethodList.size()) { 344 cmEqual = false; 345 } else { 346 Iterator it = confMethods.iterator(); 347 while (it.hasNext()) { 348 String confMethodStr = (String)it.next(); 349 if(!_confirmationMethodList.contains(confMethodStr)) { 350 cmEqual= false; 351 break; 352 } 353 } 354 } 355 // came here hence confirmations methods are equal 356 Element scData = subjectConfirmation.getSubjectConfirmationData(); 357 if (_subjectConfirmationData != null) { 358 if (scData == null) { 359 scDataEqual = false; 360 } else { 361 String thisString = printSCData(_subjectConfirmationData, 362 true, true); 363 String passString = printSCData(scData, true, true); 364 scDataEqual = thisString.equals(passString); 365 } 366 } else if (scData != null) { 367 scDataEqual= false; // one is null not the other 368 } 369 if (!(cmEqual) || !(scDataEqual)) { 370 return false; 371 } 372 } else { 373 return false; // this object atleast has mandatory confirmation 374 // method, while passed one is null hence false 375 } 376 return true; // if got here, then they are equal 377 } 378 379 private String printSCData(Element scData, 380 boolean includeNS, 381 boolean declareNS) 382 { 383 StringBuffer xml = new StringBuffer(1000); 384 xml.append(SAMLUtilsCommon.makeStartElementTagXML( 385 "SubjectConfirmationData", includeNS, declareNS)); 386 NodeList nl = scData.getChildNodes(); 387 for (int i = 0, len = nl.getLength(); i < len; i++) { 388 xml.append(XMLUtils.print(nl.item(i))); 389 } 390 xml.append(SAMLUtilsCommon.makeEndElementTagXML( 391 "SubjectConfirmationData", includeNS)); 392 return xml.toString(); 393 } 394 395 /** 396 * Returns a String representation of the element 397 * 398 * @return A string containing the valid XML for this element 399 * By default name space name is prepended to the element name 400 * example <code><saml:SubjectConfirmation></code>. 401 */ 402 public java.lang.String toString() { 403 // call toString() with includeNS true by default and declareNS false 404 String xml = this.toString(true, false); 405 return xml; 406 } 407 408 /** 409 * Returns a String representation of the 410 * <code><SubjectConfirmation></code> element. 411 * 412 * @param includeNS Determines whether or not the namespace qualifier is 413 * prepended to the Element when converted 414 * @param declareNS Determines whether or not the namespace is declared 415 * within the Element. 416 * @return A string containing the valid XML for this element. 417 */ 418 public java.lang.String toString(boolean includeNS, boolean declareNS) { 419 StringBuffer xml = new StringBuffer(3000); 420 String o = SAMLUtilsCommon.makeStartElementTagXML( 421 "SubjectConfirmation", includeNS, declareNS); 422 xml.append(o).append(sc.NL); 423 if (_confirmationMethodList.size() > 0 ) { 424 Iterator it = _confirmationMethodList.iterator(); 425 while (it.hasNext()) { 426 o = SAMLUtilsCommon.makeStartElementTagXML( 427 "ConfirmationMethod",includeNS, false); 428 xml.append(o).append((String)it.next()); 429 o = SAMLUtilsCommon.makeEndElementTagXML( 430 "ConfirmationMethod",includeNS); 431 xml.append(o); 432 } 433 } 434 435 if (_subjectConfirmationData != null) { 436 xml.append( 437 printSCData(_subjectConfirmationData, includeNS, false)); 438 } 439 if (_keyInfo != null) { 440 xml.append(XMLUtils.print(_keyInfo)); 441 } 442 o = SAMLUtilsCommon.makeEndElementTagXML("SubjectConfirmation", 443 includeNS); 444 xml.append(o); 445 return xml.toString(); 446 } 447}
Copyright © 2010-2017, ForgeRock All Rights Reserved.