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: FSNameIdentifierMappingResponse.java,v 1.2 2008/06/25 05:46:44 qcheng Exp $ 026 * Portions Copyrighted 2014 ForgeRock AS 027 */ 028 029package com.sun.identity.federation.message; 030 031import com.sun.identity.shared.xml.XMLUtils; 032 033import com.sun.identity.shared.Constants; 034import com.sun.identity.shared.DateUtils; 035import com.sun.identity.common.SystemConfigurationUtil; 036 037import com.sun.identity.federation.common.FSUtils; 038import com.sun.identity.federation.common.IFSConstants; 039import com.sun.identity.federation.message.common.FSMsgException; 040 041import com.sun.identity.saml.assertion.NameIdentifier; 042 043import com.sun.identity.saml.common.SAMLConstants; 044import com.sun.identity.saml.common.SAMLException; 045import com.sun.identity.saml.common.SAMLResponderException; 046 047import com.sun.identity.saml.protocol.AbstractResponse; 048import com.sun.identity.saml.protocol.Status; 049 050import com.sun.identity.saml.xmlsig.XMLSignatureManager; 051 052import java.util.Date; 053import java.util.List; 054 055import org.w3c.dom.Document; 056import org.w3c.dom.Element; 057import org.w3c.dom.Node; 058import org.w3c.dom.NodeList; 059 060/** 061 * The class <code>FSNameIdentifierMappingResponse</code> is used to 062 * create , parse the <code>NameIdentifierMappingResponse</code>. 063 * 064 * @supported.all.api 065 * @deprecated since 12.0.0 066 */ 067@Deprecated 068public class FSNameIdentifierMappingResponse extends AbstractResponse { 069 070 private String providerID; 071 private Status status; 072 private NameIdentifier nameIdentifier; 073 private int minorVersion = IFSConstants.FF_12_PROTOCOL_MINOR_VERSION; 074 private String signatureString; 075 076 /** 077 * Constructor to create <code>FSNameIdentifierMappingResponse</code> object. 078 * 079 * @param providerID the value of <code>ProviderID</code> attribute. 080 * @param inResponseTo the value of <code>InResponseTo</code> attribute. 081 * @param status the <code>Status</code> object. 082 * @param nameIdentifier the resulting mapped identifier, 083 * <code>NameIdentifier</code>, for the desired identity federation. 084 * @throws FSMsgException on an error. 085 */ 086 public FSNameIdentifierMappingResponse(String providerID, 087 String inResponseTo, Status status, 088 NameIdentifier nameIdentifier) throws FSMsgException { 089 this.providerID = providerID; 090 this.inResponseTo = inResponseTo; 091 this.status = status; 092 this.nameIdentifier = nameIdentifier; 093 this.responseID = FSUtils.generateID(); 094 setIssueInstant(new Date()); 095 } 096 097 /** 098 * Constructor to create <code>FSNameIdentifierMappingResponse</code> object. 099 * This object is created from the Document Element. 100 * 101 * @param root the <code>NameIdentifierMappingResponse</code> Document 102 * Element 103 * @throws FSMsgException if there is an error creating the object. 104 */ 105 public FSNameIdentifierMappingResponse(Element root) 106 throws FSMsgException { 107 if (root == null) { 108 FSUtils.debug.message( 109 "FSNameIdentifierMappingResponse: null element input"); 110 throw new FSMsgException("nullInputParameter",null); 111 } 112 String tag = null; 113 if (((tag = root.getLocalName()) == null) || 114 (!tag.equals("NameIdentifierMappingResponse"))) { 115 FSUtils.debug.message( 116 "FSNameIdentifierMappingRequest: wrong input"); 117 throw new FSMsgException("wrongInput",null); 118 } 119 120 // get IssueInstant 121 String instantString = root.getAttribute(IFSConstants.ISSUE_INSTANT); 122 if (instantString==null || instantString.length()==0) { 123 FSUtils.debug.error("FSNameIdentifierMappingResponse: " + 124 "missing IssueInstant"); 125 String[] args = { IFSConstants.ISSUE_INSTANT }; 126 throw new FSMsgException("missingAttribute",args); 127 } else { 128 try { 129 issueInstant = DateUtils.stringToDate(instantString); 130 } catch (Exception e) { 131 FSUtils.debug.error("FSNameIdentifierMappingResponse: " + 132 "could not parse IssueInstant.", e); 133 throw new FSMsgException("wrongInput",null); 134 } 135 } 136 137 // get ResponseID 138 responseID = root.getAttribute(IFSConstants.RESPONSE_ID); 139 if ((responseID == null) || (responseID.length() < 1)) { 140 FSUtils.debug.error("FSNameIdentifierMappingResponse: " + 141 "response doesn't have ResponseID"); 142 String[] args = { IFSConstants.RESPONSE_ID }; 143 throw new FSMsgException("missingAttribute",args); 144 } 145 146 // get InResponseTo 147 inResponseTo = root.getAttribute(IFSConstants.IN_RESPONSE_TO); 148 if (inResponseTo == null) { 149 FSUtils.debug.error("FSNameIdentifierMappingResponse: " + 150 "response doesn't have InResponseTo"); 151 String[] args = { IFSConstants.IN_RESPONSE_TO }; 152 throw new FSMsgException("missingAttribute",args); 153 } 154 155 // get and check versions 156 parseMajorVersion(root.getAttribute(IFSConstants.MAJOR_VERSION)); 157 parseMinorVersion(root.getAttribute(IFSConstants.MINOR_VERSION)); 158 159 // get ProviderID, Status & NameIdentifier 160 NodeList nl = root.getChildNodes(); 161 Node child; 162 String childName; 163 int length = nl.getLength(); 164 for (int i = 0; i < length; i++) { 165 child = nl.item(i); 166 if ((childName = child.getLocalName()) != null) { 167 if (childName.equals(IFSConstants.STATUS)) { 168 try { 169 status = new Status((Element) child); 170 } catch (SAMLException se) { 171 FSUtils.debug.error("FSNameIdentifierMappingResponse:" + 172 " unable to initialize Status", se); 173 throw new FSMsgException("statusCreateError",null,se); 174 } 175 } else if (childName.equals(IFSConstants.PROVIDER_ID)) { 176 providerID = XMLUtils.getElementValue((Element) child); 177 } else if (childName.equals(IFSConstants.NAME_IDENTIFIER)) { 178 try { 179 nameIdentifier = 180 new NameIdentifier((Element) child); 181 } catch (SAMLException samle) { 182 FSUtils.debug.error("FSNameIdentifierMappingResponse:" + 183 " unable to initialize NameIdentifier", samle); 184 throw new FSMsgException("nameIdentifierCreateError", 185 null,samle); 186 } 187 } 188 } 189 } 190 191 // get signature 192 List signs = XMLUtils.getElementsByTagNameNS1( 193 root, 194 SAMLConstants.XMLSIG_NAMESPACE_URI, 195 SAMLConstants.XMLSIG_ELEMENT_NAME); 196 int signsSize = signs.size(); 197 if (signsSize == 1) { 198 Element elem = (Element)signs.get(0); 199 setSignature(elem); 200 signed = true; 201 } else if (signsSize != 0) { 202 FSUtils.debug.error("FSNameIdentifierMappingResponse: " + 203 "included more than one Signature element."); 204 throw new FSMsgException("moreElement",null); 205 } 206 } 207 208 /** 209 * Creates <code>FSNameIdentifierMappingResponse</code> object. 210 * This object is created by parsing the <code>XML</code> string. 211 * 212 * @param xml the <code>XML</code> string to be parse. 213 * @return the <code>FSNameIdentifierMappingResponse</code> object. 214 * @throws FSMsgException if there is an error in parsing the 215 * <code>XML</code> string. 216 */ 217 public static FSNameIdentifierMappingResponse parseXML(String xml) 218 throws FSMsgException { 219 Document doc = XMLUtils.toDOMDocument(xml, FSUtils.debug); 220 if (doc == null) { 221 FSUtils.debug.error("FSNameIdentifierMappingResponse.parseXML: " + 222 "error while parsing input xml string"); 223 throw new FSMsgException("parseError",null); 224 } 225 Element root = doc.getDocumentElement(); 226 return new FSNameIdentifierMappingResponse(root); 227 } 228 229 /** 230 * Returns the value of <code>ProviderID</code> attribute. 231 * 232 * @return the value of <code>ProviderID</code> attribute. 233 */ 234 public String getProviderID() { 235 return providerID; 236 } 237 238 /** 239 * Returns the <code>Status</code>. 240 * 241 * @return the <code>Status</code>. 242 */ 243 public Status getStatus() { 244 return status; 245 } 246 247 /** 248 * Returns the <code>NameIdentifier</code> object. This is the resulting 249 * mapped name identifier for the desired identity federation. 250 * 251 * @return <code>NameIdentifier</code> object, the resulting mapped name 252 * identifier for the desired identity federation 253 */ 254 public NameIdentifier getNameIdentifier() { 255 return nameIdentifier; 256 } 257 258 /** 259 * Sets the <code>MajorVersion</code> by parsing the version string. 260 * 261 * @param version a String representing the <code>MajorVersion</code> to 262 * be set. 263 * @throws FSMsgException on error. 264 */ 265 private void parseMajorVersion(String version) throws FSMsgException { 266 try { 267 majorVersion = Integer.parseInt(version); 268 } catch (NumberFormatException e) { 269 if (FSUtils.debug.messageEnabled()) { 270 FSUtils.debug.message("FSNameIdentifierMappingResponse." + 271 "parseMajorVersion:invalid MajorVersion:" + version, e); 272 } 273 throw new FSMsgException("wrongInput",null); 274 } 275 276 if (majorVersion != SAMLConstants.PROTOCOL_MAJOR_VERSION) { 277 if (majorVersion > SAMLConstants.PROTOCOL_MAJOR_VERSION) { 278 if (FSUtils.debug.messageEnabled()) { 279 FSUtils.debug.message("FSNameIdentifierMappingResponse." + 280 "parseMajorVersion: MajorVersion is too high"); 281 } 282 throw new FSMsgException("requestVersionTooHigh",null); 283 } else { 284 if (FSUtils.debug.messageEnabled()) { 285 FSUtils.debug.message("FSNameIdentifierMappingResponse." + 286 "parseMajorVersion: MajorVersion is too low"); 287 } 288 throw new FSMsgException("requestVersionTooLow",null); 289 } 290 } 291 } 292 293 /** 294 * Sets the <code>MinorVersion</code> by parsing the version string. 295 * 296 * @param minorVer a String representing the <code>MinorVersion</code> to 297 * be set. 298 * @throws FSMsgException when the version mismatchs. 299 */ 300 private void parseMinorVersion(String version) throws FSMsgException { 301 try { 302 minorVersion = Integer.parseInt(version); 303 } catch (NumberFormatException e) { 304 if (FSUtils.debug.messageEnabled()) { 305 FSUtils.debug.message("FSNameIdentifierMappingResponse." + 306 "parseMinorVersion:invalid MinorVersion:" + version, e); 307 } 308 throw new FSMsgException("wrongInput",null); 309 } 310 if (minorVersion > IFSConstants.FF_12_PROTOCOL_MINOR_VERSION) { 311 if (FSUtils.debug.messageEnabled()) { 312 FSUtils.debug.message("FSNameIdentifierMappingResponse." + 313 "parseMinorVersion: MinorVersion is too high"); 314 } 315 throw new FSMsgException("requestVersionTooHigh",null); 316 } else if (minorVersion < IFSConstants.FF_11_PROTOCOL_MINOR_VERSION) { 317 if (FSUtils.debug.messageEnabled()) { 318 FSUtils.debug.message("FSNameIdentifierMappingResponse." + 319 "parseMinorVersion: MinorVersion is too low"); 320 } 321 throw new FSMsgException("requestVersionTooLow",null); 322 } 323 } 324 325 /** 326 * Signs the XML document representing 327 * <code>NameIdentifierMappingResponse</code> using the certificate 328 * indicated by the property "com.sun.identity.saml.xmlsig.certalias" 329 * in AMConfig.properties file. 330 * 331 * @throws SAMLException if there is an error signing 332 * the <code>XML</code> string. 333 */ 334 public void signXML() throws SAMLException { 335 String certAlias = SystemConfigurationUtil.getProperty( 336 Constants.SAML_XMLSIG_CERT_ALIAS); 337 signXML(certAlias); 338 } 339 340 /** 341 * Signs the <code>XML</code> document representing 342 * <code>NameIdentifierMappingResponse</code> using the specified 343 * certificate. 344 * 345 * @param certAlias the alias/name of the certificate used for signing 346 * the XML document 347 * @throws SAMLException if there is an error signing 348 * the <code>XML</code> string or if the message is already 349 * signed. 350 */ 351 public void signXML(String certAlias) throws SAMLException { 352 FSUtils.debug.message("FSNameIdentifierMappingResponse.signXML"); 353 if (signed) { 354 if (FSUtils.debug.messageEnabled()) { 355 FSUtils.debug.message("FSNameIdentifierMappingResponse.signXML:" 356 + " the response is already signed."); 357 } 358 throw new SAMLResponderException(FSUtils.BUNDLE_NAME, 359 "alreadySigned",null); 360 } 361 if (certAlias == null || certAlias.length() < 1) { 362 if (FSUtils.debug.messageEnabled()) { 363 FSUtils.debug.message("FSNameIdentifierMappingResponse.signXML:" 364 + " null certAlias"); 365 } 366 throw new SAMLResponderException(FSUtils.BUNDLE_NAME, 367 "cannotFindCertAlias",null); 368 } 369 try { 370 XMLSignatureManager manager = XMLSignatureManager.getInstance(); 371 signatureString = manager.signXML(this.toXMLString(true, true), 372 certAlias, (String)null, 373 IFSConstants.RESPONSE_ID, 374 this.getResponseID(), false); 375 signature = XMLUtils.toDOMDocument(signatureString, FSUtils.debug) 376 .getDocumentElement(); 377 signed = true; 378 } catch (Exception e){ 379 FSUtils.debug.error("FSNameIdentifierMappingResponse.signXML: " + 380 "unable to sign", e); 381 throw new SAMLResponderException( 382 FSUtils.BUNDLE_NAME,"signFailed",null); 383 } 384 } 385 386 /** 387 * Returns the string representation of this object. 388 * 389 * @return An XML String representing the object. 390 * @throws FSMsgException on error. 391 */ 392 public String toXMLString() throws FSMsgException { 393 return toXMLString(true, true); 394 } 395 396 /** 397 * Returns a String representation of this object. 398 * 399 * @param includeNS : Determines whether or not the namespace qualifier 400 * is prepended to the Element when converted 401 * @param declareNS : Determines whether or not the namespace is declared 402 * within the Element. 403 * @return a string containing the valid XML for this element 404 * @throws FSMsgException if there is an error converting 405 * this object ot a string. 406 */ 407 408 public String toXMLString(boolean includeNS, boolean declareNS) 409 throws FSMsgException { 410 return toXMLString(includeNS, declareNS, false); 411 } 412 413 /** 414 * Returns a String representation of this object. 415 * 416 * @param includeNS Determines whether or not the namespace qualifier 417 * is prepended to the Element when converted 418 * @param declareNS Determines whether or not the namespace is declared 419 * within the Element. 420 * @param includeHeader Determines whether the output include the xml 421 * declaration header. 422 * @return a string containing the valid XML for this element 423 * @throws FSMsgException if there is an error converting 424 * this object ot a string. 425 */ 426 public String toXMLString(boolean includeNS, boolean declareNS, 427 boolean includeHeader) throws FSMsgException { 428 429 String prefixLIB = ""; 430 String uriLIB = ""; 431 String uriSAML = ""; 432 if (includeNS) { 433 prefixLIB = IFSConstants.LIB_PREFIX; 434 } 435 if (declareNS) { 436 uriLIB = IFSConstants.LIB_12_NAMESPACE_STRING; 437 uriSAML = IFSConstants.assertionDeclareStr; 438 } 439 String instantString = null; 440 try { 441 instantString = DateUtils.toUTCDateFormat(issueInstant); 442 } catch (Exception e) { 443 FSUtils.debug.error("FSNameIdentifierMappingResponse.toXMLString:" + 444 " could not convert issueInstant to String.", e); 445 } 446 // construct xml response 447 StringBuffer xml = new StringBuffer(1000); 448 if (includeHeader) { 449 xml.append(IFSConstants.XML_PREFIX) 450 .append(SAMLConstants.DEFAULT_ENCODING) 451 .append(IFSConstants.QUOTE) 452 .append(IFSConstants.SPACE) 453 .append(IFSConstants.QUESTION_MARK) 454 .append(IFSConstants.RIGHT_ANGLE) 455 .append(IFSConstants.NL); 456 } 457 xml.append(IFSConstants.LEFT_ANGLE) 458 .append(prefixLIB) 459 .append(IFSConstants.NAMEID_MAPPING_RESPONSE) 460 .append(uriLIB).append(uriSAML) 461 .append(IFSConstants.SPACE) 462 .append(IFSConstants.RESPONSE_ID) 463 .append(IFSConstants.EQUAL_TO) 464 .append(IFSConstants.QUOTE) 465 .append(responseID) 466 .append(IFSConstants.QUOTE) 467 .append(IFSConstants.SPACE) 468 .append(IFSConstants.IN_RESPONSE_TO) 469 .append(IFSConstants.EQUAL_TO) 470 .append(IFSConstants.QUOTE) 471 .append(inResponseTo) 472 .append(IFSConstants.QUOTE) 473 .append(IFSConstants.SPACE) 474 .append(IFSConstants.SPACE) 475 .append(IFSConstants.MAJOR_VERSION) 476 .append(IFSConstants.EQUAL_TO) 477 .append(IFSConstants.QUOTE) 478 .append(majorVersion) 479 .append(IFSConstants.EQUAL_TO) 480 .append(IFSConstants.QUOTE) 481 .append(IFSConstants.SPACE) 482 .append(IFSConstants.SPACE) 483 .append(IFSConstants.MINOR_VERSION) 484 .append(IFSConstants.EQUAL_TO) 485 .append(IFSConstants.QUOTE) 486 .append(minorVersion) 487 .append(IFSConstants.QUOTE) 488 .append(IFSConstants.SPACE) 489 .append(IFSConstants.SPACE) 490 .append(IFSConstants.ISSUE_INSTANT) 491 .append(IFSConstants.EQUAL_TO) 492 .append(instantString) 493 .append(IFSConstants.QUOTE) 494 .append(IFSConstants.SPACE) 495 .append(IFSConstants.RIGHT_ANGLE); 496 if (signed) { 497 if (signatureString != null) { 498 xml.append(signatureString); 499 } else if (signature != null) { 500 signatureString = XMLUtils.print(signature); 501 xml.append(signatureString); 502 } 503 } 504 xml.append(IFSConstants.LEFT_ANGLE) 505 .append(prefixLIB) 506 .append(IFSConstants.PROVIDER_ID) 507 .append(IFSConstants.RIGHT_ANGLE) 508 .append(providerID) 509 .append(IFSConstants.START_END_ELEMENT) 510 .append(prefixLIB) 511 .append(IFSConstants.PROVIDER_ID) 512 .append(IFSConstants.RIGHT_ANGLE) 513 .append(status.toString(includeNS, true)); 514 515 if (nameIdentifier != null) { 516 xml.append(nameIdentifier.toString()); 517 } 518 xml.append(IFSConstants.START_END_ELEMENT) 519 .append(prefixLIB) 520 .append(IFSConstants.NAMEID_MAPPING_RESPONSE) 521 .append(IFSConstants.RIGHT_ANGLE); 522 523 return xml.toString(); 524 } 525}
Copyright © 2010-2017, ForgeRock All Rights Reserved.