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: FSLogoutResponse.java,v 1.4 2008/06/25 05:46:44 qcheng Exp $ 026 * 027 * Portions Copyrighted 2014-2016 ForgeRock AS. 028 */ 029 030package com.sun.identity.federation.message; 031 032import static org.forgerock.http.util.Uris.urlEncodeQueryParameterNameOrValue; 033import static org.forgerock.openam.utils.Time.*; 034 035import com.sun.identity.shared.encode.Base64; 036import com.sun.identity.shared.xml.XMLUtils; 037 038import com.sun.identity.shared.DateUtils; 039 040import com.sun.identity.federation.message.common.FSMsgException; 041import com.sun.identity.federation.common.FSUtils; 042import com.sun.identity.federation.common.IFSConstants; 043 044import com.sun.identity.saml.common.SAMLConstants; 045import com.sun.identity.saml.common.SAMLException; 046import com.sun.identity.saml.common.SAMLResponderException; 047import com.sun.identity.saml.common.SAMLVersionMismatchException; 048 049import com.sun.identity.saml.xmlsig.XMLSignatureManager; 050 051import com.sun.identity.saml.protocol.AbstractResponse; 052import com.sun.identity.saml.protocol.Status; 053import com.sun.identity.saml.protocol.StatusCode; 054 055import java.io.IOException; 056 057import java.text.ParseException; 058 059import java.util.Date; 060import java.util.List; 061 062import javax.servlet.http.HttpServletRequest; 063 064import org.w3c.dom.Element; 065import org.w3c.dom.Node; 066import org.w3c.dom.NodeList; 067import org.w3c.dom.Document; 068 069/** 070 * This class has methods to create a Liberty <code>LogoutResponse</code>. 071 * 072 * @supported.all.api 073 * @deprecated since 12.0.0 074 */ 075@Deprecated 076public class FSLogoutResponse extends AbstractResponse { 077 private String providerId; 078 private String relayState; 079 private Status status; 080 protected String xmlString; 081 protected String signatureString; 082 protected String id; 083 private String inResponseTo; 084 085 /** 086 * Default Constructor. 087 */ 088 public FSLogoutResponse() { 089 try { 090 setIssueInstant(newDate()); 091 providerId = new String(); 092 StatusCode statusCode = new StatusCode(IFSConstants.SAML_SUCCESS); 093 status = new Status(statusCode); 094 relayState = new String(); 095 } catch (SAMLException e){ 096 FSUtils.debug.error("FSLogoutResponse.constructor:", e); 097 } 098 099 } 100 101 /** 102 * Constructor creates <code>FSLogoutResponse</code> object. 103 * 104 * @param responseID the value of <code>ResponseID</code> attribute. 105 * @param inResponseTo the value of <code>inResponseTo</code> attribute. 106 * @param status the Logout <code>Status</code> object. 107 * @param providerId the value of <code>ProviderID</code> attribute. 108 * @param relayState the value of <code>RelayState</code> attribute. 109 * @throws <code>FSMsgException</code> if this object cannot be created. 110 */ 111 public FSLogoutResponse(String responseID, 112 String inResponseTo, 113 Status status, 114 String providerId, 115 String relayState) 116 throws FSMsgException { 117 if ((responseID == null) || (responseID.length() == 0)) { 118 this.responseID = FSUtils.generateID(); 119 if (this.responseID == null) { 120 throw new FSMsgException("errorGenerateID",null); 121 } 122 } else { 123 this.responseID = responseID; 124 } 125 126 if (inResponseTo == null) { 127 FSUtils.debug.message("Response: inResponseTo is null."); 128 throw new FSMsgException("nullInput",null); 129 } 130 this.inResponseTo = inResponseTo; 131 if (status == null) { 132 FSUtils.debug.message("Response: missing <Status>."); 133 throw new FSMsgException("missingElement",null); 134 } 135 this.status = status; 136 this.providerId = providerId; 137 this.relayState = relayState; 138 setIssueInstant(newDate()); 139 } 140 141 /** 142 * Constructor creates <code>FSLogoutResponse</code> object from 143 * a Document element. 144 * 145 * @param root the Document element object. 146 * @throws FSMsgException if this object cannot be created. 147 * @throws SAMLException if there is an error. 148 */ 149 public FSLogoutResponse(Element root) throws FSMsgException, SAMLException { 150 if (root == null) { 151 FSUtils.debug.message("FSLogoutResponse.parseXML: null input."); 152 throw new FSMsgException("nullInput",null); 153 } 154 String tag = null; 155 if (((tag = root.getLocalName()) == null) || 156 (!tag.equals(IFSConstants.LOGOUT_RESPONSE))) { 157 FSUtils.debug.message("FSLogoutResponse.parseXML: wrong input."); 158 throw new FSMsgException("wrongInput",null); 159 } 160 161 id = root.getAttribute(IFSConstants.ID); 162 163 // Attribute ResponseID 164 responseID = root.getAttribute(IFSConstants.RESPONSE_ID); 165 if ((responseID == null) || (responseID.length() == 0)) { 166 if (FSUtils.debug.messageEnabled()) { 167 FSUtils.debug.message("FSLogoutResponse.parseXML: " 168 + "Reponse doesn't have ResponseID."); 169 } 170 String[] args = { IFSConstants.RESPONSE_ID }; 171 throw new FSMsgException("missingAttribute",args); 172 } 173 parseMajorVersion(root.getAttribute(IFSConstants.MAJOR_VERSION)); 174 parseMinorVersion(root.getAttribute(IFSConstants.MINOR_VERSION)); 175 // Attribute InResponseTo 176 inResponseTo = root.getAttribute(IFSConstants.IN_RESPONSE_TO); 177 if (inResponseTo == null) { 178 if (FSUtils.debug.messageEnabled()) { 179 FSUtils.debug.message("FSLogoutResponse.parseXML: " 180 + "Response doesn't have InResponseTo."); 181 } 182 String[] args = { IFSConstants.IN_RESPONSE_TO }; 183 throw new FSMsgException("missingAttribute",args); 184 } 185 // Attribute IssueInstant 186 String instantString = root.getAttribute(IFSConstants.ISSUE_INSTANT); 187 if ((instantString == null) || (instantString.length() == 0)) { 188 FSUtils.debug.message("FSLogoutResponse(Element): " 189 + "missing IssueInstant"); 190 String[] args = { IFSConstants.ISSUE_INSTANT }; 191 throw new FSMsgException("missingAttribute",args); 192 } else { 193 try { 194 issueInstant = DateUtils.stringToDate(instantString); 195 } catch (ParseException e) { 196 if (FSUtils.debug.messageEnabled()) { 197 FSUtils.debug.message( 198 "FSLogoutResponse(Element): could not " + 199 "parse IssueInstant", e); 200 } 201 throw new FSMsgException("wrongInput", null); 202 } 203 } 204 205 NodeList nl = root.getChildNodes(); 206 Node child; 207 String childName; 208 int length = nl.getLength(); 209 for (int i = 0; i < length; i++) { 210 child = nl.item(i); 211 if ((childName = child.getLocalName()) != null) { 212 if (childName.equals(IFSConstants.STATUS)) { 213 if (status != null) { 214 if (FSUtils.debug.messageEnabled()) { 215 FSUtils.debug.message( 216 "FSLogoutResponse: included more" 217 + " than one <Status>"); 218 } 219 throw new FSMsgException("moreElement",null); 220 } 221 status = new Status((Element) child); 222 } else if (childName.equals(IFSConstants.SIGNATURE)) { 223 } else if (childName.equals(IFSConstants.PROVIDER_ID)) { 224 if (providerId != null) { 225 if (FSUtils.debug.messageEnabled()) { 226 FSUtils.debug.message( 227 "FSLogoutResponse: included more" 228 + " than one providerId"); 229 } 230 throw new FSMsgException("moreElement",null); 231 } 232 providerId = XMLUtils.getElementValue((Element) child); 233 } else if (childName.equals(IFSConstants.RELAY_STATE)) { 234 relayState = XMLUtils.getElementValue((Element) child); 235 } else { 236 if (FSUtils.debug.messageEnabled()) { 237 FSUtils.debug.message("FSLogoutResponse: included wrong" 238 + " element:" + childName); 239 } 240 throw new FSMsgException("wrongInput",null); 241 } 242 } // end if childName != null 243 } // end for loop 244 245 if (status == null) { 246 FSUtils.debug.message("FSLogoutResponse:missing element <Status>."); 247 throw new FSMsgException("oneElement",null); 248 } 249 250 if (providerId == null) { 251 FSUtils.debug.message( 252 "FSLogoutResponse: missing element providerId."); 253 throw new FSMsgException("oneElement",null); 254 } 255 256 //check for signature 257 List signs = XMLUtils.getElementsByTagNameNS1(root, 258 SAMLConstants.XMLSIG_NAMESPACE_URI, 259 SAMLConstants.XMLSIG_ELEMENT_NAME); 260 int signsSize = signs.size(); 261 if (signsSize == 1) { 262 Element elem = (Element)signs.get(0); 263 setSignature(elem); 264 xmlString = XMLUtils.print(root); 265 signed = true; 266 } else if (signsSize != 0) { 267 if (FSUtils.debug.messageEnabled()) { 268 FSUtils.debug.message( 269 "FSLogoutResponse(Element): included more than" 270 + " one Signature element."); 271 } 272 throw new FSMsgException("moreElement",null); 273 } 274 } 275 276 /** 277 * Returns the value of <code>RelayState</code> attribute. 278 * 279 * @return the value of <code>RelayState</code> attribute. 280 * @see #setRelayState(String) 281 */ 282 public String getRelayState(){ 283 return relayState; 284 } 285 286 /** 287 * Set the value of <code>RelayState</code> attribute. 288 * 289 * @param relayState the value of <code>RelayState</code> attribute. 290 * @see #getRelayState() 291 */ 292 public void setRelayState(String relayState){ 293 this.relayState = relayState; 294 } 295 296 /** 297 * Returns the value of <code>InResponseTo</code> attribute. 298 * 299 * @return the value of <code>InResponseTo</code> attribute. 300 * @see #setResponseTo(String) 301 */ 302 public String getResponseTo(){ 303 return inResponseTo; 304 } 305 306 /** 307 * Sets the value of <code>InResponseTo</code> attribute. 308 * 309 * @param inResponseTo the value of <code>InResponseTo</code> attribute. 310 * @see #getResponseTo 311 */ 312 public void setResponseTo(String inResponseTo){ 313 this.inResponseTo = inResponseTo; 314 } 315 316 /** 317 * Returns the value of <code>id</code> attribute. 318 * 319 * @return the value of <code>id</code> attribute. 320 * @see #setID(String) 321 */ 322 public String getID(){ 323 return id; 324 } 325 326 /** 327 * Sets the value of <code>id</code> attribute. 328 * 329 * @param id the value of <code>id</code> attribute. 330 * @see #getID() 331 */ 332 public void setID(String id){ 333 this.id = id; 334 } 335 336 /** 337 * Returns the value of <code>ProviderID</code> attribute. 338 * 339 * @return the value of <code>ProviderID</code> attribute. 340 * @see #setProviderId(String). 341 */ 342 343 public String getProviderId(){ 344 return providerId; 345 } 346 347 /** 348 * Sets the value of <code>ProviderID</code> attribute. 349 * 350 * @param providerId the value of <code>ProviderID</code> attribute. 351 * @see #getProviderId() 352 */ 353 public void setProviderId(String providerId){ 354 this.providerId = providerId; 355 } 356 357 /** 358 * Returns the Signed <code>LogoutResponse</code> string. 359 * 360 * @return signatureString the Signed <code>LogoutResponse</code> string. 361 */ 362 public String getSignatureString(){ 363 return signatureString; 364 } 365 366 /** 367 * Returns the value of <code>MinorVersion</code> attribute. 368 * 369 * @return the value of <code>MinorVersion</code> attribute. 370 * @see #setMinorVersion(int) 371 */ 372 public int getMinorVersion() { 373 return minorVersion; 374 } 375 376 /** 377 * Sets the value of <code>MinorVersion</code> attribute. 378 * 379 * @param version thevalue of <code>MinorVersion</code> attribute. 380 * @see #getMinorVersion() 381 */ 382 public void setMinorVersion(int version) { 383 minorVersion = version; 384 } 385 386 /** 387 * Returns the Logout <code>Status</code>. 388 * 389 * @return the Logout <code>Status</code>. 390 * @see #setStatus(String) 391 * @see #setStatus(Status) 392 */ 393 public Status getStatus() { 394 return status; 395 } 396 397 /** 398 * Sets the Logout <code>Status</code>. 399 * 400 * @param status the Logout <code>Status</code code. 401 * @see #getStatus 402 */ 403 public void setStatus(String status) { 404 try { 405 StatusCode statusCode = new StatusCode(status); 406 this.status = new Status(statusCode); 407 } catch (Exception e) { 408 if (FSUtils.debug.messageEnabled()) { 409 FSUtils.debug.message("FSLogoutResponse(Element): could not " 410 + "set attribute:", e); 411 } 412 } 413 } 414 415 /** 416 * Sets the Logout <code>Status</code>. 417 * 418 * @param status the Logout <code>Status</code object. 419 * @see #getStatus 420 */ 421 public void setStatus(Status status) { 422 this.status=status; 423 } 424 425 /** 426 * Sets the <code>MajorVersion</code> by parsing the version string. 427 * 428 * @param majorVer a String representing the <code>MajorVersion</code> to 429 * be set. 430 * @throws FSMsgException on error. 431 * @throws SAMLException when the version mismatchs. 432 */ 433 private void parseMajorVersion(String majorVer) 434 throws FSMsgException, SAMLException { 435 try { 436 majorVersion = Integer.parseInt(majorVer); 437 } catch (NumberFormatException e) { 438 if (FSUtils.debug.messageEnabled()) { 439 FSUtils.debug.message("Response(Element): invalid " 440 + "MajorVersion", e); 441 } 442 throw new FSMsgException("wrongInput",null); 443 } 444 445 if (majorVersion != SAMLConstants.PROTOCOL_MAJOR_VERSION) { 446 if (majorVersion > SAMLConstants.PROTOCOL_MAJOR_VERSION) { 447 if (FSUtils.debug.messageEnabled()) { 448 FSUtils.debug.message("Response(Element):MajorVersion of" 449 + " the Response is too high."); 450 } 451 throw new SAMLVersionMismatchException(FSUtils.BUNDLE_NAME, 452 "responseVersionTooHigh",null); 453 } else { 454 if (FSUtils.debug.messageEnabled()) { 455 FSUtils.debug.message("Response(Element):MajorVersion of" 456 + " the Response is too low."); 457 } 458 throw new SAMLVersionMismatchException(FSUtils.BUNDLE_NAME, 459 "responseVersionTooLow",null); 460 } 461 } 462 } 463 464 /** 465 * Sets the <code>MinorVersion</code> by parsing the version string. 466 * 467 * @param minorVer a String representing the <code>MinorVersion</code> to 468 * be set. 469 * @throws SAMLException when the version mismatchs. 470 */ 471 private void parseMinorVersion(String minorVer) 472 throws FSMsgException, SAMLException { 473 try { 474 minorVersion = Integer.parseInt(minorVer); 475 } catch (NumberFormatException e) { 476 if (FSUtils.debug.messageEnabled()) { 477 FSUtils.debug.message("Response(Element): invalid " 478 + "MinorVersion", e); 479 } 480 throw new FSMsgException("wrongInput",null); 481 } 482 if (minorVersion > IFSConstants.FF_12_PROTOCOL_MINOR_VERSION) { 483 FSUtils.debug.error("Response(Element):MinorVersion of" 484 + " the Response is too high."); 485 throw new SAMLVersionMismatchException(FSUtils.BUNDLE_NAME, 486 "responseVersionTooHigh",null); 487 } else if (minorVersion < IFSConstants.FF_11_PROTOCOL_MINOR_VERSION) { 488 FSUtils.debug.error("Response(Element):MinorVersion of" 489 + " the Response is too low."); 490 throw new SAMLVersionMismatchException(FSUtils.BUNDLE_NAME, 491 "responseVersionTooLow",null); 492 } 493 } 494 495 /** 496 * Returns the <code>FSLogoutResponse</code> object. 497 * 498 * @param xml the XML string to be parsed. 499 * @return <code>FSLogoutResponse</code> object created from the XML string. 500 * @throws FSMsgException if there is 501 * error creating the object. 502 */ 503 504 public static FSLogoutResponse parseXML(String xml) throws FSMsgException { 505 FSLogoutResponse logoutResponse = null; 506 try{ 507 Document doc = XMLUtils.toDOMDocument(xml, FSUtils.debug); 508 Element root = doc.getDocumentElement(); 509 logoutResponse = new FSLogoutResponse(root); 510 }catch(SAMLException ex){ 511 if (FSUtils.debug.messageEnabled()) { 512 FSUtils.debug.message("FSLogoutResponse.parseXML: " 513 + "Error while parsing input xml string"); 514 } 515 throw new FSMsgException("parseError",null, ex); 516 } 517 return logoutResponse; 518 } 519 520 /** 521 * Returns a String representation of the <code>LogoutResponse</code> 522 * object. This method translates the response to an XML string. 523 * 524 * @return An XML String representing the logout response. 525 */ 526 public String toXMLString() throws FSMsgException { 527 return this.toXMLString(true, true); 528 } 529 530 /** 531 * Returns a String representation of the <code>LogoutResponse</code> 532 * object. 533 * 534 * @return An XML String representing the logout response. 535 * @throws FSMsgException if there is an error converting 536 * this object ot a string. 537 */ 538 public String toXMLString(boolean includeNS, boolean declareNS) 539 throws FSMsgException { 540 return toXMLString(includeNS, declareNS, false); 541 } 542 543 /** 544 * Returns a String representation of the <code>LogoutResponse</code> 545 * object. 546 * 547 * @param includeNS Determines whether or not the namespace qualifier 548 * is prepended to the Element when converted 549 * @param declareNS Determines whether or not the namespace is declared 550 * within the Element. 551 * @param includeHeader Determines whether the output include the xml 552 * declaration header. 553 * @return a string containing the valid XML for this element 554 * @throws FSMsgException if there is an error converting 555 * this object ot a string. 556 */ 557 558 public String toXMLString(boolean includeNS, boolean declareNS, 559 boolean includeHeader) throws FSMsgException { 560 StringBuffer xml = new StringBuffer(300); 561 if (includeHeader) { 562 xml.append(IFSConstants.XML_PREFIX) 563 .append(SAMLConstants.DEFAULT_ENCODING) 564 .append(IFSConstants.QUOTE) 565 .append(IFSConstants.SPACE) 566 .append(IFSConstants.QUESTION_MARK) 567 .append(IFSConstants.RIGHT_ANGLE) 568 .append(IFSConstants.NL); 569 } 570 String prefixLIB = ""; 571 String uriLIB = ""; 572 if (includeNS) { 573 prefixLIB = IFSConstants.LIB_PREFIX; 574 } 575 576 if (declareNS) { 577 if(minorVersion == IFSConstants.FF_12_PROTOCOL_MINOR_VERSION) { 578 uriLIB = IFSConstants.LIB_12_NAMESPACE_STRING; 579 } else { 580 uriLIB = IFSConstants.LIB_NAMESPACE_STRING; 581 } 582 } 583 584 String instantString = DateUtils.toUTCDateFormat(issueInstant); 585 586 if((providerId == null) || (providerId.length() == 0)){ 587 FSUtils.debug.error("FSLogoutResponse.toXMLString: " 588 + "providerId is null in the response with responseId:" 589 + responseID); 590 String[] args = { responseID }; 591 throw new FSMsgException("nullProviderIdWResponseId",args); 592 } 593 594 xml.append(IFSConstants.LEFT_ANGLE) 595 .append(prefixLIB) 596 .append(IFSConstants.LOGOUT_RESPONSE) 597 .append(uriLIB) 598 .append(IFSConstants.SPACE); 599 600 if (minorVersion == IFSConstants.FF_11_PROTOCOL_MINOR_VERSION && 601 id != null && !(id.length() == 0)) { 602 xml.append(IFSConstants.ID) 603 .append(IFSConstants.EQUAL_TO) 604 .append(IFSConstants.QUOTE) 605 .append(id) 606 .append(IFSConstants.QUOTE) 607 .append(IFSConstants.SPACE) 608 .append(IFSConstants.SPACE); 609 } 610 611 if (responseID != null) { 612 xml.append(IFSConstants.RESPONSE_ID) 613 .append(IFSConstants.EQUAL_TO) 614 .append(IFSConstants.QUOTE) 615 .append(responseID) 616 .append(IFSConstants.QUOTE) 617 .append(IFSConstants.SPACE) 618 .append(IFSConstants.SPACE); 619 } 620 621 if (inResponseTo != null) { 622 xml.append(IFSConstants.IN_RESPONSE_TO) 623 .append(IFSConstants.EQUAL_TO) 624 .append(IFSConstants.QUOTE) 625 .append(inResponseTo) 626 .append(IFSConstants.QUOTE) 627 .append(IFSConstants.SPACE) 628 .append(IFSConstants.SPACE); 629 } 630 631 xml.append(IFSConstants.MAJOR_VERSION) 632 .append(IFSConstants.EQUAL_TO) 633 .append(IFSConstants.QUOTE) 634 .append(majorVersion) 635 .append(IFSConstants.QUOTE) 636 .append(IFSConstants.SPACE) 637 .append(IFSConstants.SPACE) 638 .append(IFSConstants.MINOR_VERSION) 639 .append(IFSConstants.EQUAL_TO) 640 .append(IFSConstants.QUOTE) 641 .append(minorVersion) 642 .append(IFSConstants.QUOTE) 643 .append(IFSConstants.SPACE) 644 .append(IFSConstants.SPACE) 645 .append(IFSConstants.ISSUE_INSTANT) 646 .append(IFSConstants.EQUAL_TO) 647 .append(IFSConstants.QUOTE) 648 .append(instantString) 649 .append(IFSConstants.QUOTE) 650 .append(IFSConstants.RIGHT_ANGLE); 651 652 if (signed) { 653 if (signatureString != null) { 654 xml.append(signatureString); 655 } else if (signature != null) { 656 signatureString = XMLUtils.print(signature); 657 xml.append(signatureString); 658 } 659 } 660 661 if (providerId != null) { 662 xml.append(IFSConstants.LEFT_ANGLE) 663 .append(prefixLIB) 664 .append(IFSConstants.PROVIDER_ID) 665 .append(IFSConstants.RIGHT_ANGLE) 666 .append(providerId) 667 .append(IFSConstants.START_END_ELEMENT) 668 .append(prefixLIB) 669 .append(IFSConstants.PROVIDER_ID) 670 .append(IFSConstants.RIGHT_ANGLE); 671 } 672 673 if (status != null) { 674 xml.append(status.toString(includeNS, true)); 675 } 676 677 if (relayState != null) { 678 xml.append(IFSConstants.LEFT_ANGLE) 679 .append(prefixLIB) 680 .append(IFSConstants.RELAY_STATE) 681 .append(IFSConstants.RIGHT_ANGLE) 682 .append(relayState) 683 .append(IFSConstants.START_END_ELEMENT) 684 .append(prefixLIB) 685 .append(IFSConstants.RELAY_STATE) 686 .append(IFSConstants.RIGHT_ANGLE); 687 } 688 689 xml.append(IFSConstants.START_END_ELEMENT) 690 .append(prefixLIB) 691 .append(IFSConstants.LOGOUT_RESPONSE) 692 .append(IFSConstants.RIGHT_ANGLE); 693 694 return xml.toString(); 695 } 696 697 /** 698 * Returns <code>FSLogoutResponse</code> object. The object 699 * is created by parsing an Base64 encode authentication 700 * request String. 701 * 702 * @param encodedRes the encode string 703 * @throws FSMsgException if there is an error creating this object. 704 * @throws SAMLException if there is an error creating this object. 705 */ 706 public static FSLogoutResponse parseBASE64EncodedString(String encodedRes) 707 throws FSMsgException, SAMLException { 708 if (encodedRes != null){ 709 String decodedNameRegRes = new String(Base64.decode(encodedRes)); 710 if (FSUtils.debug.messageEnabled()) { 711 FSUtils.debug.message("FSLogoutResponse." 712 + "parseBASE64EncodedString: decoded input string: " 713 + decodedNameRegRes); 714 } 715 return parseXML(decodedNameRegRes); 716 } else { 717 if (FSUtils.debug.messageEnabled()) { 718 FSUtils.debug.message( 719 "FSLogoutResponse.parseBASE64EncodedString" 720 + ": null String passed in as argument."); 721 } 722 throw new FSMsgException("nullInput",null); 723 } 724 } 725 726 /** 727 * Returns a Base64 Encoded String. 728 * 729 * @return a Base64 Encoded String. 730 * @throws FSMsgException if there is an error encoding the string. 731 */ 732 public String toBASE64EncodedString() throws FSMsgException { 733 if ((responseID == null) || (responseID.length() == 0)){ 734 responseID = FSUtils.generateID(); 735 if (responseID == null) { 736 FSUtils.debug.error("FSLogoutResponse.toBASE64EncodedString: " 737 + "couldn't generate ResponseID."); 738 throw new FSMsgException("errorGenerateID",null); 739 } 740 } 741 return Base64.encode(this.toXMLString().getBytes()); 742 } 743 744 /** 745 * Unsupported operation. 746 */ 747 public void signXML() { 748 } 749 750 /** 751 * Signs the <code>LogoutResponse</code>. 752 * 753 * @param certAlias the Certificate Alias. 754 * @throws XMLSignatureException if this object cannot be signed. 755 */ 756 public void signXML(String certAlias) throws SAMLException { 757 FSUtils.debug.message("FSLogoutResponse.signXML: Called"); 758 if (signed) { 759 if (FSUtils.debug.messageEnabled()) { 760 FSUtils.debug.message("FSLogoutResponse.signXML: " 761 + "the assertion is already signed."); 762 } 763 throw new SAMLResponderException(FSUtils.BUNDLE_NAME, 764 "alreadySigned",null); 765 } 766 if (certAlias == null || certAlias.length() == 0) { 767 throw new SAMLResponderException(FSUtils.BUNDLE_NAME, 768 "cannotFindCertAlias",null); 769 } 770 try{ 771 XMLSignatureManager manager = XMLSignatureManager.getInstance(); 772 if (minorVersion == IFSConstants.FF_11_PROTOCOL_MINOR_VERSION) { 773 signatureString = manager.signXML(this.toXMLString(true, true), 774 certAlias, 775 IFSConstants.DEF_SIG_ALGO, 776 IFSConstants.ID, 777 this.id, false); 778 } else if (minorVersion == 779 IFSConstants.FF_12_PROTOCOL_MINOR_VERSION) { 780 signatureString = 781 manager.signXML(this.toXMLString(true, true), 782 certAlias, IFSConstants.DEF_SIG_ALGO, 783 IFSConstants.RESPONSE_ID, 784 this.getResponseID(), false); 785 } else { 786 if (FSUtils.debug.messageEnabled()) { 787 FSUtils.debug.message("invalid minor version."); 788 } 789 } 790 791 signature = XMLUtils.toDOMDocument(signatureString, FSUtils.debug) 792 .getDocumentElement(); 793 794 signed = true; 795 xmlString = this.toXMLString(true, true); 796 } catch (Exception e) { 797 throw new SAMLResponderException(FSUtils.BUNDLE_NAME, 798 "signFailed",null); 799 } 800 } 801 802 /** 803 * Sets the Signature. 804 * 805 * @param elem the Document Element. 806 * @return true if success otherwise false. 807 */ 808 public boolean setSignature(Element elem) { 809 signatureString = XMLUtils.print(elem); 810 return super.setSignature(elem); 811 } 812 813 /** 814 * Returns an URL Encoded String. 815 * 816 * @return a url encoded query string. 817 * @throws FSMsgException if there is an error. 818 */ 819 public String toURLEncodedQueryString() throws FSMsgException { 820 if ((providerId == null) || (providerId.length() == 0)) { 821 FSUtils.debug.error("FSLogoutResponse." 822 + "toURLEncodedQueryString: providerId is null in " 823 + "the response "); 824 throw new FSMsgException("nullProviderIdInRequest",null); 825 } 826 if ((responseID == null) || (responseID.length() == 0)){ 827 responseID = FSUtils.generateID(); 828 if (responseID == null) { 829 FSUtils.debug.error("FSNameRegistrationRequest." 830 + "toURLEncodedQueryString: couldn't generate " 831 + "responseID."); 832 throw new FSMsgException("errorGenerateID",null); 833 } 834 } 835 836 StringBuffer urlEncodedAuthnReq = new StringBuffer(300); 837 urlEncodedAuthnReq.append(IFSConstants.RESPONSE_ID) 838 .append(IFSConstants.EQUAL_TO) 839 .append(urlEncodeQueryParameterNameOrValue(responseID)) 840 .append(IFSConstants.AMPERSAND); 841 842 if((inResponseTo != null) && (inResponseTo.length() > 0)) { 843 urlEncodedAuthnReq.append(IFSConstants.IN_RESPONSE_TO) 844 .append(IFSConstants.EQUAL_TO) 845 .append(urlEncodeQueryParameterNameOrValue(inResponseTo)) 846 .append(IFSConstants.AMPERSAND); 847 } 848 urlEncodedAuthnReq.append(IFSConstants.MAJOR_VERSION) 849 .append(IFSConstants.EQUAL_TO) 850 .append(majorVersion) 851 .append(IFSConstants.AMPERSAND) 852 .append(IFSConstants.MINOR_VERSION) 853 .append(IFSConstants.EQUAL_TO) 854 .append(minorVersion) 855 .append(IFSConstants.AMPERSAND); 856 857 if (issueInstant != null) { 858 urlEncodedAuthnReq.append(IFSConstants.ISSUE_INSTANT) 859 .append(IFSConstants.EQUAL_TO) 860 .append(urlEncodeQueryParameterNameOrValue( 861 DateUtils.toUTCDateFormat(issueInstant))) 862 .append(IFSConstants.AMPERSAND); 863 } else { 864 FSUtils.debug.error("FSLogoutResponse." 865 + "toURLEncodedQueryString: issueInstant missing"); 866 String[] args = { IFSConstants.ISSUE_INSTANT }; 867 throw new FSMsgException("missingAttribute",args); 868 } 869 if(providerId != null && providerId.length() != 0) { 870 urlEncodedAuthnReq.append(IFSConstants.PROVIDER_ID) 871 .append(IFSConstants.EQUAL_TO) 872 .append(urlEncodeQueryParameterNameOrValue(providerId)) 873 .append(IFSConstants.AMPERSAND); 874 } 875 876 if(relayState != null && relayState.length() != 0) { 877 urlEncodedAuthnReq.append(IFSConstants.RELAY_STATE) 878 .append(IFSConstants.EQUAL_TO) 879 .append(urlEncodeQueryParameterNameOrValue(relayState)) 880 .append(IFSConstants.AMPERSAND); 881 } 882 883 if (status != null) { 884 urlEncodedAuthnReq.append(IFSConstants.VALUE) 885 .append(IFSConstants.EQUAL_TO) 886 .append(urlEncodeQueryParameterNameOrValue( 887 status.getStatusCode().getValue())) 888 .append(IFSConstants.AMPERSAND); 889 } 890 return urlEncodedAuthnReq.toString(); 891 } 892 893 894 /** 895 * Returns <code>FSLogoutResponse</code> object. The 896 * object is creating by parsing the <code>HttpServletRequest</code> 897 * object. 898 * 899 * @param request the <code>HttpServletRequest</code> object. 900 * @throws FSMsgException if there is an error creating this object. 901 * @throws SAMLException if there is an error. 902 */ 903 public static FSLogoutResponse parseURLEncodedRequest( 904 HttpServletRequest request) 905 throws FSMsgException, SAMLException { 906 FSLogoutResponse retLogoutResponse = new FSLogoutResponse(); 907 try { 908 FSUtils.debug.message("checking minor version"); 909 retLogoutResponse.majorVersion = 910 Integer.parseInt( 911 request.getParameter(IFSConstants.MAJOR_VERSION)); 912 retLogoutResponse.minorVersion = 913 Integer.parseInt( 914 request.getParameter(IFSConstants.MINOR_VERSION)); 915 } catch(NumberFormatException ex){ 916 throw new FSMsgException("invalidNumber",null); 917 } 918 919 String requestID = request.getParameter(IFSConstants.RESPONSE_ID); 920 if (requestID != null) { 921 retLogoutResponse.responseID = requestID ; 922 } else { 923 String[] args = { IFSConstants.RESPONSE_ID }; 924 throw new FSMsgException("missingAttribute",args); 925 } 926 retLogoutResponse.inResponseTo = 927 request.getParameter(IFSConstants.IN_RESPONSE_TO); 928 929 String instantString = 930 request.getParameter(IFSConstants.ISSUE_INSTANT); 931 if (instantString == null || instantString.length() == 0) { 932 String[] args = { IFSConstants.ISSUE_INSTANT }; 933 throw new FSMsgException("missingAttribute",args); 934 } 935 try{ 936 retLogoutResponse.issueInstant = 937 DateUtils.stringToDate(instantString); 938 } catch (ParseException e){ 939 throw new FSMsgException("parseError",null); 940 } 941 FSUtils.debug.message(" get provider Id"); 942 String providerID = request.getParameter(IFSConstants.PROVIDER_ID); 943 if (providerID != null) { 944 retLogoutResponse.providerId = providerID; 945 if (FSUtils.debug.messageEnabled()) { 946 FSUtils.debug.message("ProviderID : " 947 + retLogoutResponse.providerId); 948 } 949 } else { 950 if (FSUtils.debug.messageEnabled()) { 951 FSUtils.debug.message("ProviderID : " 952 + retLogoutResponse.providerId); 953 } 954 throw new FSMsgException("missingElement",null); 955 } 956 957 String relayState = request.getParameter(IFSConstants.RELAY_STATE); 958 if (relayState != null) { 959 retLogoutResponse.relayState = relayState; 960 if (FSUtils.debug.messageEnabled()) { 961 FSUtils.debug.message("RelayState:" 962 + retLogoutResponse.relayState); 963 } 964 } 965 966 String value = request.getParameter(IFSConstants.VALUE); 967 if (value != null){ 968 if (FSUtils.debug.messageEnabled()) { 969 FSUtils.debug.message("Status : " + value); 970 } 971 StatusCode statusCode = new StatusCode(value); 972 retLogoutResponse.status = new Status(statusCode); 973 } else { 974 if (FSUtils.debug.messageEnabled()) { 975 FSUtils.debug.message("Status : " + value); 976 } 977 throw new FSMsgException("missingElement",null); 978 } 979 980 FSUtils.debug.message("Returning Logout response Object"); 981 return retLogoutResponse; 982 } 983 }