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