001/* 002 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 003 * 004 * Copyright (c) 2008 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: AssertionIDRequestUtil.java,v 1.8 2009/06/12 22:21:40 mallas Exp $ 026 * 027 * Portions Copyrighted 2013-2016 ForgeRock AS. 028 */ 029package com.sun.identity.saml2.profile; 030 031import static org.forgerock.openam.utils.Time.*; 032 033import java.io.BufferedInputStream; 034import java.io.BufferedOutputStream; 035import java.io.IOException; 036import java.io.UnsupportedEncodingException; 037import java.net.HttpURLConnection; 038import java.net.MalformedURLException; 039import java.net.URL; 040import java.security.PrivateKey; 041import java.security.cert.X509Certificate; 042import java.util.ArrayList; 043import java.util.Date; 044import java.util.Hashtable; 045import java.util.Iterator; 046import java.util.List; 047import java.util.Set; 048import javax.servlet.http.HttpServletRequest; 049import javax.servlet.http.HttpServletResponse; 050import javax.xml.soap.SOAPException; 051import javax.xml.soap.SOAPMessage; 052 053import com.sun.identity.saml2.common.SAML2FailoverUtils; 054import com.sun.identity.saml2.common.SOAPCommunicator; 055import org.forgerock.openam.federation.saml2.SAML2TokenRepositoryException; 056import com.sun.identity.common.HttpURLConnectionManager; 057import org.w3c.dom.Element; 058 059import com.sun.identity.saml.xmlsig.KeyProvider; 060import com.sun.identity.saml.common.SAMLUtils; 061import com.sun.identity.saml2.assertion.Assertion; 062import com.sun.identity.saml2.assertion.AssertionFactory; 063import com.sun.identity.saml2.assertion.AssertionIDRef; 064import com.sun.identity.saml2.assertion.Issuer; 065import com.sun.identity.saml2.common.SAML2Constants; 066import com.sun.identity.saml2.common.SAML2Exception; 067import com.sun.identity.saml2.common.SAML2Utils; 068import com.sun.identity.saml2.jaxb.entityconfig.BaseConfigType; 069import com.sun.identity.saml2.jaxb.metadata.AttributeAuthorityDescriptorElement; 070import com.sun.identity.saml2.jaxb.metadata.AssertionIDRequestServiceElement; 071import com.sun.identity.saml2.jaxb.metadata.AuthnAuthorityDescriptorElement; 072import com.sun.identity.saml2.jaxb.metadata.IDPSSODescriptorElement; 073import com.sun.identity.saml2.jaxb.metadata.RoleDescriptorType; 074import com.sun.identity.saml2.jaxb.metadata.SPSSODescriptorElement; 075import com.sun.identity.saml2.key.KeyUtil; 076import com.sun.identity.saml2.meta.SAML2MetaException; 077import com.sun.identity.saml2.meta.SAML2MetaManager; 078import com.sun.identity.saml2.plugins.AssertionIDRequestMapper; 079import com.sun.identity.saml2.protocol.AssertionIDRequest; 080import com.sun.identity.saml2.protocol.ProtocolFactory; 081import com.sun.identity.saml2.protocol.Response; 082import com.sun.identity.saml2.protocol.Status; 083import com.sun.identity.saml2.protocol.StatusCode; 084 085/** 086 * This class provides methods to send or process 087 * <code>AssertionIDRequest</code>. 088 * 089 * @supported.api 090 */ 091public class AssertionIDRequestUtil { 092 093 static KeyProvider keyProvider = KeyUtil.getKeyProviderInstance(); 094 static SAML2MetaManager metaManager = SAML2Utils.getSAML2MetaManager(); 095 static Hashtable assertionIDRequestMapperCache = new Hashtable(); 096 static final String MIME_TYPE_ASSERTION = "application/samlassertion+xml"; 097 098 private AssertionIDRequestUtil() { 099 } 100 101 /** 102 * Sends the <code>AssertionIDRequest</code> to specifiied Assertion ID 103 * Request Service and returns <code>Response</code> coming from the 104 * Assertion ID Request Service. 105 * 106 * @param assertionIDRequest the <code>AssertionIDRequest</code> object 107 * @param samlAuthorityEntityID entity ID of SAML authority 108 * @param role SAML authority role, for example, 109 * <code>SAML2Constants.ATTR_AUTH_ROLE</code>, 110 * <code>SAML2Constants.AUTHN_AUTH_ROLE</code> or 111 * <code>SAML2Constants.IDP_ROLE</code> 112 * @param realm the realm of hosted entity 113 * @param binding the binding 114 * 115 * @return the <code>Response</code> object 116 * @exception SAML2Exception if the operation is not successful 117 * 118 * @supported.api 119 */ 120 public static Response sendAssertionIDRequest( 121 AssertionIDRequest assertionIDRequest, String samlAuthorityEntityID, 122 String role, String realm, String binding) throws SAML2Exception { 123 124 StringBuffer location = new StringBuffer(); 125 RoleDescriptorType roled = getRoleDescriptorAndLocation( 126 samlAuthorityEntityID, role, realm, binding, location); 127 128 if (binding.equalsIgnoreCase(SAML2Constants.SOAP)) { 129 signAssertionIDRequest(assertionIDRequest, realm, false); 130 return sendAssertionIDRequestBySOAP(assertionIDRequest, 131 location.toString(), realm, samlAuthorityEntityID, role, roled); 132 } else { 133 throw new SAML2Exception( 134 SAML2Utils.bundle.getString("unsupportedBinding")); 135 } 136 } 137 138 /** 139 * Sends the Assertion ID to specifiied Assertion ID Request Service and 140 * returns <code>Assertion</code> coming from the Assertion ID Request 141 * Service. 142 * 143 * @param assertionID the asssertionID</code> object 144 * @param samlAuthorityEntityID entity ID of SAML authority 145 * @param role SAML authority role, for example, 146 * <code>SAML2Constants.ATTR_AUTH_ROLE</code>, 147 * <code>SAML2Constants.AUTHN_AUTH_ROLE</code> or 148 * <code>SAML2Constants.IDP_ROLE</code> 149 * @param realm the realm of hosted entity 150 * 151 * @return the <code>Assertion</code> object 152 * @exception SAML2Exception if the operation is not successful 153 * 154 * @supported.api 155 */ 156 public static Assertion sendAssertionIDRequestURI( 157 String assertionID, String samlAuthorityEntityID, 158 String role, String realm) throws SAML2Exception { 159 160 StringBuffer locationSB = new StringBuffer(); 161 getRoleDescriptorAndLocation(samlAuthorityEntityID, role, realm, 162 SAML2Constants.URI, locationSB); 163 if (locationSB.indexOf("?") == -1) { 164 locationSB.append("?"); 165 } else { 166 locationSB.append("&"); 167 } 168 locationSB.append("ID=").append(assertionID); 169 String location = fillInBasicAuthInfo(locationSB.toString(), realm, 170 samlAuthorityEntityID, role); 171 172 URL url = null; 173 try { 174 url = new URL(location); 175 } catch (MalformedURLException me) { 176 throw new SAML2Exception(me.getMessage()); 177 } 178 179 try { 180 HttpURLConnection conn = HttpURLConnectionManager.getConnection(url); 181 conn.setInstanceFollowRedirects(false); 182 conn.setUseCaches(false); 183 conn.setDoOutput(false); 184 conn.connect(); 185 186 int respCode = conn.getResponseCode(); 187 if (SAML2Utils.debug.messageEnabled()) { 188 SAML2Utils.debug.message( 189 "AssertionIDRequestUtil.sendAssertionIDRequestURI: " + 190 "Response code = " + respCode + ", Response message = " + 191 conn.getResponseMessage()); 192 } 193 if (respCode != HttpURLConnection.HTTP_OK) { 194 return null; 195 } 196 197 String contentType = conn.getContentType(); 198 if (SAML2Utils.debug.messageEnabled()) { 199 SAML2Utils.debug.message( 200 "AssertionIDRequestUtil.sendAssertionIDRequestURI: " + 201 "Content type = " + contentType); 202 } 203 if ((contentType == null) || 204 (contentType.indexOf(MIME_TYPE_ASSERTION) == -1)) { 205 206 return null; 207 } 208 209 int contentLength = conn.getContentLength(); 210 if (SAML2Utils.debug.messageEnabled()) { 211 SAML2Utils.debug.message( 212 "AssertionIDRequestUtil.sendAssertionIDRequestURI: " + 213 "Content length = " + contentLength); 214 } 215 216 BufferedInputStream bin = 217 new BufferedInputStream(conn.getInputStream()); 218 StringBuffer contentSB = new StringBuffer(); 219 byte content[] = new byte[2048]; 220 221 if (contentLength != -1) { 222 int read = 0, totalRead = 0; 223 int left; 224 while (totalRead < contentLength) { 225 left = contentLength - totalRead; 226 read = bin.read(content, 0, 227 left < content.length ? left : content.length); 228 if (read == -1) { 229 // We need to close connection !! 230 break; 231 } else { 232 if (read > 0) { 233 totalRead += read; 234 contentSB.append(new String(content, 0, read)); 235 } 236 } 237 } 238 } else { 239 int numbytes; 240 int totalRead = 0; 241 242 while (true) { 243 numbytes = bin.read(content); 244 if (numbytes == -1) { 245 break; 246 } 247 248 totalRead += numbytes; 249 contentSB.append(new String(content, 0, numbytes)); 250 } 251 } 252 253 return AssertionFactory.getInstance().createAssertion( 254 contentSB.toString()); 255 } catch (IOException ioex) { 256 SAML2Utils.debug.error( 257 "AssertionIDRequest.sendAssertionIDRequestURI:", ioex); 258 throw new SAML2Exception(ioex.getMessage()); 259 } 260 } 261 262 /** 263 * Gets assertion ID from URI and returns assertion if found. 264 * 265 * @param request the <code>HttpServletRequest</code> object 266 * @param response the <code>HttpServletResponse</code> object 267 * @param samlAuthorityEntityID entity ID of SAML authority 268 * @param role SAML authority role 269 * @param realm the realm of hosted entity 270 * 271 * @exception IOException if response can't be sent 272 */ 273 public static void processAssertionIDRequestURI(HttpServletRequest request, 274 HttpServletResponse response, String samlAuthorityEntityID, 275 String role, String realm) throws IOException { 276 277 String assertionID = request.getParameter("ID"); 278 if (assertionID == null) { 279 SAMLUtils.sendError(request, response, 280 HttpServletResponse.SC_BAD_REQUEST, "nullAssertionID", 281 SAML2Utils.bundle.getString("nullAssertionID")); 282 return; 283 } 284 285 AssertionIDRequestMapper aidReqMapper = null; 286 try { 287 aidReqMapper = getAssertionIDRequestMapper(realm, 288 samlAuthorityEntityID, role); 289 } catch (SAML2Exception ex) { 290 SAMLUtils.sendError(request, response, 291 HttpServletResponse.SC_INTERNAL_SERVER_ERROR, 292 "failedToGetAssertionIDRequestMapper", ex.getMessage()); 293 return; 294 } 295 296 try { 297 aidReqMapper.authenticateRequesterURI(request, response, 298 samlAuthorityEntityID, role, realm); 299 } catch (SAML2Exception ex) { 300 SAMLUtils.sendError(request, response, 301 HttpServletResponse.SC_FORBIDDEN, 302 "failedToAuthenticateRequesterURI", ex.getMessage()); 303 return; 304 } 305 306 Assertion assertion = (Assertion)IDPCache.assertionByIDCache.get( 307 assertionID); 308 309 if ((assertion == null) || (!assertion.isTimeValid())) { 310 SAMLUtils.sendError(request, response, 311 HttpServletResponse.SC_NOT_FOUND, 312 "invalidAssertionID", 313 SAML2Utils.bundle.getString("invalidAssertionID")); 314 return; 315 } 316 317 response.setContentType(MIME_TYPE_ASSERTION); 318 response.addHeader("Cache-Control", "no-cache, no-store"); 319 response.addHeader("Pragma", "no-cache"); 320 321 String content = null; 322 try { 323 content = assertion.toXMLString(true, true); 324 } catch (SAML2Exception ex) { 325 if (SAML2Utils.debug.messageEnabled()) { 326 SAML2Utils.debug.message("AssertionIDRequestUtil." + 327 "processAssertionIDRequestURI:", ex); 328 } 329 SAMLUtils.sendError(request, response, 330 HttpServletResponse.SC_INTERNAL_SERVER_ERROR, 331 "invalidAssertion", ex.getMessage()); 332 return; 333 } 334 335 byte[] bytes = null; 336 try { 337 bytes = content.getBytes("UTF-8"); 338 } catch(UnsupportedEncodingException ueex) { 339 if (SAML2Utils.debug.messageEnabled()) { 340 SAML2Utils.debug.message("AssertionIDRequestUtil." + 341 "processAssertionIDRequestURI:", ueex); 342 } 343 SAMLUtils.sendError(request, response, 344 HttpServletResponse.SC_INTERNAL_SERVER_ERROR, 345 "unsupportedEncoding", ueex.getMessage()); 346 return; 347 } 348 response.setContentLength(bytes.length); 349 350 BufferedOutputStream bos = null; 351 try { 352 bos = new BufferedOutputStream(response.getOutputStream()); 353 bos.write(bytes, 0, bytes.length); 354 } catch (IOException ioex) { 355 SAML2Utils.debug.error("AssertionIDRequestUtil." + 356 "processAssertionIDRequestURI:", ioex); 357 } finally { 358 if (bos != null) { 359 try { 360 bos.close(); 361 } catch (IOException ioex) { 362 SAML2Utils.debug.error("AssertionIDRequestUtil." + 363 "processAssertionIDRequestURI:", ioex); 364 } 365 } 366 } 367 } 368 369 /** 370 * This method processes the <code>AssertionIDRequest</code> coming 371 * from a requester. 372 * 373 * @param assertionIDRequest the <code>AssertionIDRequest</code> object 374 * @param request the <code>HttpServletRequest</code> object 375 * @param response the <code>HttpServletResponse</code> object 376 * @param samlAuthorityEntityID entity ID of SAML authority 377 * @param role the role of SAML authority 378 * @param realm the realm of SAML authority 379 * @return the <code>Response</code> object 380 * @exception SAML2Exception if the operation is not successful 381 */ 382 public static Response processAssertionIDRequest( 383 AssertionIDRequest assertionIDRequest, HttpServletRequest request, 384 HttpServletResponse response, String samlAuthorityEntityID, 385 String role, String realm) throws SAML2Exception { 386 387 try { 388 verifyAssertionIDRequest(assertionIDRequest, samlAuthorityEntityID, 389 role, realm); 390 } catch(SAML2Exception se) { 391 SAML2Utils.debug.error("AssertionIDRequestUtil." + 392 "processAssertionIDRequest:", se); 393 return SAML2Utils.getErrorResponse(assertionIDRequest, 394 SAML2Constants.REQUESTER, null, se.getMessage(), 395 samlAuthorityEntityID); 396 } 397 398 Issuer issuer = assertionIDRequest.getIssuer(); 399 String spEntityID = issuer.getValue(); 400 401 RoleDescriptorType roled = null; 402 try { 403 if (SAML2Constants.IDP_ROLE.equals(role)) { 404 roled = metaManager.getIDPSSODescriptor(realm, 405 samlAuthorityEntityID); 406 } else if (SAML2Constants.AUTHN_AUTH_ROLE.equals(role)) { 407 roled = metaManager.getAuthnAuthorityDescriptor(realm, 408 samlAuthorityEntityID); 409 } else if (SAML2Constants.ATTR_AUTH_ROLE.equals(role)) { 410 roled = metaManager.getAttributeAuthorityDescriptor(realm, 411 samlAuthorityEntityID); 412 } 413 } catch (SAML2MetaException sme) { 414 SAML2Utils.debug.error("AssertionIDRequestUtil." + 415 "processAssertionIDRequest:", sme); 416 return SAML2Utils.getErrorResponse(assertionIDRequest, 417 SAML2Constants.RESPONDER, null, sme.getMessage(), 418 samlAuthorityEntityID); 419 } 420 421 if (roled == null) { 422 return SAML2Utils.getErrorResponse(assertionIDRequest, 423 SAML2Constants.REQUESTER, null, SAML2Utils.bundle.getString( 424 "samlAuthorityNotFound"), samlAuthorityEntityID); 425 } 426 427 List returnAssertions = null; 428 List assertionIDRefs = assertionIDRequest.getAssertionIDRefs(); 429 for(Iterator iter = assertionIDRefs.iterator(); iter.hasNext();) { 430 AssertionIDRef assertionIDRef = (AssertionIDRef)iter.next(); 431 String assertionID = assertionIDRef.getValue(); 432 433 Assertion assertion = (Assertion)IDPCache.assertionByIDCache.get( 434 assertionID); 435 if ((assertion == null) && (SAML2FailoverUtils.isSAML2FailoverEnabled())) { 436 if (SAML2Utils.debug.messageEnabled()) { 437 SAML2Utils.debug.message("AssertionIDRequestUtil.processAssertionIDRequest: " + 438 "reading assertion from the SAML2 Token Repository using assertionID:" + assertionID); 439 } 440 String assertionStr = null; 441 try { 442 assertionStr = (String) SAML2FailoverUtils.retrieveSAML2Token(assertionID); 443 } catch (SAML2TokenRepositoryException se) { 444 SAML2Utils.debug.error("AssertionIDRequestUtil.processAssertionIDRequest: " + 445 "There was a problem reading assertion from the SAML2 Token Repository using assertionID:" 446 + assertionID, se); 447 } 448 if (assertionStr != null) { 449 assertion = AssertionFactory.getInstance().createAssertion( 450 assertionStr); 451 } 452 } 453 454 if ((assertion != null) && (assertion.isTimeValid())) { 455 if (returnAssertions == null) { 456 returnAssertions = new ArrayList(); 457 } 458 returnAssertions.add(assertion); 459 } 460 } 461 462 ProtocolFactory protocolFactory = ProtocolFactory.getInstance(); 463 Response samlResp = protocolFactory.createResponse(); 464 samlResp.setAssertion(returnAssertions); 465 466 samlResp.setID(SAML2Utils.generateID()); 467 samlResp.setInResponseTo(assertionIDRequest.getID()); 468 469 samlResp.setVersion(SAML2Constants.VERSION_2_0); 470 samlResp.setIssueInstant(newDate()); 471 472 Status status = protocolFactory.createStatus(); 473 StatusCode statusCode = protocolFactory.createStatusCode(); 474 statusCode.setValue(SAML2Constants.SUCCESS); 475 status.setStatusCode(statusCode); 476 samlResp.setStatus(status); 477 478 Issuer respIssuer = AssertionFactory.getInstance().createIssuer(); 479 respIssuer.setValue(samlAuthorityEntityID); 480 samlResp.setIssuer(respIssuer); 481 482 signResponse(samlResp, samlAuthorityEntityID, role, realm, false); 483 484 return samlResp; 485 } 486 487 private static RoleDescriptorType getRoleDescriptorAndLocation( 488 String samlAuthorityEntityID, String role, String realm, 489 String binding, StringBuffer location) throws SAML2Exception { 490 491 List aIDReqServices = null; 492 RoleDescriptorType roled = null; 493 try { 494 if (role == null) { 495 throw new SAML2Exception(SAML2Utils.bundle.getString( 496 "unsupportedRole")); 497 } else if (role.equals(SAML2Constants.IDP_ROLE)) { 498 IDPSSODescriptorElement idpd = 499 metaManager.getIDPSSODescriptor(realm, 500 samlAuthorityEntityID); 501 if (idpd == null) { 502 throw new SAML2Exception(SAML2Utils.bundle.getString( 503 "idpNotFound")); 504 } 505 aIDReqServices = idpd.getAssertionIDRequestService(); 506 roled = idpd; 507 } else if (role.equals(SAML2Constants.AUTHN_AUTH_ROLE)) { 508 AuthnAuthorityDescriptorElement attrd = 509 metaManager.getAuthnAuthorityDescriptor(realm, 510 samlAuthorityEntityID); 511 if (attrd == null) { 512 throw new SAML2Exception(SAML2Utils.bundle.getString( 513 "authnAuthorityNotFound")); 514 } 515 aIDReqServices = attrd.getAssertionIDRequestService(); 516 roled = attrd; 517 } else if (role.equals(SAML2Constants.ATTR_AUTH_ROLE)) { 518 AttributeAuthorityDescriptorElement aad = 519 metaManager.getAttributeAuthorityDescriptor(realm, 520 samlAuthorityEntityID); 521 if (aad == null) { 522 throw new SAML2Exception(SAML2Utils.bundle.getString( 523 "attrAuthorityNotFound")); 524 } 525 aIDReqServices = aad.getAssertionIDRequestService(); 526 roled = aad; 527 } else { 528 throw new SAML2Exception(SAML2Utils.bundle.getString( 529 "unsupportedRole")); 530 } 531 } catch (SAML2MetaException sme) { 532 SAML2Utils.debug.error( 533 "AssertionIDRequest.getRoleDescriptorAndLocation:", sme); 534 throw new SAML2Exception(SAML2Utils.bundle.getString( 535 "metaDataError")); 536 } 537 538 if (binding == null) { 539 throw new SAML2Exception( 540 SAML2Utils.bundle.getString("unsupportedBinding")); 541 } 542 543 if ((aIDReqServices == null) || (aIDReqServices.isEmpty())) { 544 throw new SAML2Exception( 545 SAML2Utils.bundle.getString("aIDReqServiceNotFound")); 546 } 547 548 for(Iterator iter = aIDReqServices.iterator(); iter.hasNext(); ) { 549 AssertionIDRequestServiceElement aIDReqService = 550 (AssertionIDRequestServiceElement)iter.next(); 551 if (binding.equalsIgnoreCase(aIDReqService.getBinding())) { 552 location.append(aIDReqService.getLocation()); 553 break; 554 } 555 } 556 if (location.length() == 0) { 557 throw new SAML2Exception( 558 SAML2Utils.bundle.getString("unsupportedBinding")); 559 } 560 561 return roled; 562 } 563 564 private static void signAssertionIDRequest( 565 AssertionIDRequest assertionIDRequest, 566 String realm, boolean includeCert) throws SAML2Exception { 567 568 String spEntityID = assertionIDRequest.getIssuer().getValue(); 569 570 String alias = SAML2Utils.getSigningCertAlias(realm, spEntityID, 571 SAML2Constants.SP_ROLE); 572 573 PrivateKey signingKey = keyProvider.getPrivateKey(alias); 574 X509Certificate signingCert = null; 575 if (includeCert) { 576 signingCert = keyProvider.getX509Certificate(alias); 577 } 578 579 if (signingKey != null) { 580 assertionIDRequest.sign(signingKey, signingCert); 581 } 582 } 583 584 private static void verifyAssertionIDRequest( 585 AssertionIDRequest assertionIDRequest, String samlAuthorityEntityID, 586 String role, String realm) throws SAML2Exception { 587 588 Issuer issuer = assertionIDRequest.getIssuer(); 589 String requestedEntityID = issuer.getValue(); 590 591 if (!SAML2Utils.isSourceSiteValid(issuer, realm, 592 samlAuthorityEntityID)) { 593 594 throw new SAML2Exception(SAML2Utils.bundle.getString( 595 "assertionIDRequestIssuerInvalid")); 596 } 597 598 SPSSODescriptorElement spSSODesc = metaManager.getSPSSODescriptor( 599 realm, requestedEntityID); 600 if (spSSODesc == null) { 601 throw new SAML2Exception(SAML2Utils.bundle.getString( 602 "assertionIDRequestIssuerNotFound")); 603 } 604 605 Set<X509Certificate> verificationCerts = KeyUtil.getVerificationCerts(spSSODesc, requestedEntityID, 606 SAML2Constants.SP_ROLE); 607 608 if (!verificationCerts.isEmpty()) { 609 boolean valid = assertionIDRequest.isSignatureValid(verificationCerts); 610 if (SAML2Utils.debug.messageEnabled()) { 611 SAML2Utils.debug.message( 612 "AssertionIDRequestUtil.verifyAssertionIDRequest: " + 613 "Signature validity is : " + valid); 614 } 615 if (!valid) { 616 throw new SAML2Exception(SAML2Utils.bundle.getString( 617 "invalidSignatureAssertionIDRequest")); 618 } 619 } else { 620 throw new SAML2Exception( 621 SAML2Utils.bundle.getString("missingSigningCertAlias")); 622 } 623 } 624 625 private static void signResponse(Response response, 626 String samlAuthorityEntityID, String role, String realm, 627 boolean includeCert) throws SAML2Exception { 628 629 String alias = SAML2Utils.getSigningCertAlias(realm, samlAuthorityEntityID, role); 630 631 String encryptedKeyPass = SAML2Utils.getSigningCertEncryptedKeyPass(realm, samlAuthorityEntityID, role); 632 PrivateKey signingKey; 633 if (encryptedKeyPass == null || encryptedKeyPass.isEmpty()) { 634 signingKey = keyProvider.getPrivateKey(alias); 635 } else { 636 signingKey = keyProvider.getPrivateKey(alias, encryptedKeyPass); 637 } 638 X509Certificate signingCert = null; 639 if (includeCert) { 640 signingCert = keyProvider.getX509Certificate(alias); 641 } 642 643 if (signingKey != null) { 644 response.sign(signingKey, signingCert); 645 } 646 } 647 648 private static String fillInBasicAuthInfo(String location, String realm, 649 String samlAuthorityEntityID, String role) { 650 651 BaseConfigType config = null; 652 try { 653 if (role.equals(SAML2Constants.IDP_ROLE)) { 654 config = metaManager.getIDPSSOConfig(realm, 655 samlAuthorityEntityID); 656 } else if (role.equals(SAML2Constants.AUTHN_AUTH_ROLE)) { 657 config = metaManager.getAuthnAuthorityConfig(realm, 658 samlAuthorityEntityID); 659 } else if (role.equals(SAML2Constants.ATTR_AUTH_ROLE)) { 660 config = metaManager.getAttributeAuthorityConfig(realm, 661 samlAuthorityEntityID); 662 } 663 } catch (SAML2MetaException sme) { 664 if (SAML2Utils.debug.messageEnabled()) { 665 SAML2Utils.debug.message( 666 "AssertionIDRequestUtil.getSSOConfig:", sme); 667 } 668 } 669 670 return SAML2Utils.fillInBasicAuthInfo(config, location); 671 } 672 673 private static Response sendAssertionIDRequestBySOAP( 674 AssertionIDRequest assertionIDRequest, String location, String realm, 675 String samlAuthorityEntityID, String role, RoleDescriptorType roled) 676 throws SAML2Exception { 677 678 String aIDReqStr = assertionIDRequest.toXMLString(true, true); 679 if (SAML2Utils.debug.messageEnabled()) { 680 SAML2Utils.debug.message( 681 "AssertionIDRequestUtil.sendAssertionIDRequestBySOAP: " + 682 "assertionIDRequest = " + aIDReqStr); 683 SAML2Utils.debug.message( 684 "AssertionIDRequestUtil.sendAssertionIDRequestBySOAP: " + 685 "location = " + location); 686 } 687 688 location = fillInBasicAuthInfo(location, realm, samlAuthorityEntityID, 689 role); 690 691 SOAPMessage resMsg = null; 692 try { 693 resMsg = SOAPCommunicator.getInstance().sendSOAPMessage(aIDReqStr, location, true); 694 } catch (SOAPException se) { 695 SAML2Utils.debug.error( 696 "AssertionIDRequestUtil.sendAssertionIDRequestBySOAP:", se); 697 throw new SAML2Exception( 698 SAML2Utils.bundle.getString("errorSendingAssertionIDRequest")); 699 } 700 701 Element respElem = SOAPCommunicator.getInstance().getSamlpElement(resMsg, "Response"); 702 Response response = 703 ProtocolFactory.getInstance().createResponse(respElem); 704 705 if (SAML2Utils.debug.messageEnabled()) { 706 SAML2Utils.debug.message( 707 "AssertionIDRequestUtil.sendAssertionIDRequestBySOAP: " + 708 "response = " + response.toXMLString(true, true)); 709 } 710 711 verifyResponse(response, assertionIDRequest, samlAuthorityEntityID, 712 role, roled); 713 714 return response; 715 } 716 717 private static void verifyResponse(Response response, 718 AssertionIDRequest assertionIDRequest, String samlAuthorityEntityID, 719 String role, RoleDescriptorType roled) throws SAML2Exception { 720 721 String aIDReqID = assertionIDRequest.getID(); 722 if ((aIDReqID != null) && 723 (!aIDReqID.equals(response.getInResponseTo()))) { 724 725 throw new SAML2Exception(SAML2Utils.bundle.getString( 726 "invalidInResponseToAssertionIDRequest")); 727 } 728 729 Issuer respIssuer = response.getIssuer(); 730 if (respIssuer == null) { 731 return; 732 } 733 734 if (!samlAuthorityEntityID.equals(respIssuer.getValue())) { 735 throw new SAML2Exception(SAML2Utils.bundle.getString( 736 "responseIssuerMismatch")); 737 } 738 739 740 Set<X509Certificate> signingCerts = KeyUtil.getVerificationCerts(roled, samlAuthorityEntityID, role); 741 742 if (!signingCerts.isEmpty()) { 743 boolean valid = response.isSignatureValid(signingCerts); 744 if (SAML2Utils.debug.messageEnabled()) { 745 SAML2Utils.debug.message( 746 "AssertionIDRequestUtil .verifyResponse: " + 747 "Signature validity is : " + valid); 748 } 749 if (!valid) { 750 throw new SAML2Exception(SAML2Utils.bundle.getString( 751 "invalidSignatureOnResponse")); 752 } 753 } else { 754 throw new SAML2Exception(SAML2Utils.bundle.getString("missingSigningCertAlias")); 755 } 756 757 } 758 759 private static AssertionIDRequestMapper getAssertionIDRequestMapper( 760 String realm, String samlAuthorityEntityID, String role) 761 throws SAML2Exception { 762 763 String aidReqMapperName = null; 764 AssertionIDRequestMapper aidReqMapper = null; 765 try { 766 aidReqMapperName = SAML2Utils.getAttributeValueFromSSOConfig(realm, 767 samlAuthorityEntityID, role, 768 SAML2Constants.ASSERTION_ID_REQUEST_MAPPER); 769 770 if (aidReqMapperName == null) { 771 aidReqMapperName = 772 SAML2Constants.DEFAULT_ASSERTION_ID_REQUEST_MAPPER_CLASS; 773 if (SAML2Utils.debug.messageEnabled()) { 774 SAML2Utils.debug.message( 775 "AssertionIDRequestUtil.getAssertionIDRequestMapper:" + 776 " use "+ aidReqMapperName); 777 } 778 } 779 aidReqMapper = (AssertionIDRequestMapper) 780 assertionIDRequestMapperCache.get(aidReqMapperName); 781 if (aidReqMapper == null) { 782 aidReqMapper = (AssertionIDRequestMapper) 783 Class.forName(aidReqMapperName).newInstance(); 784 assertionIDRequestMapperCache.put(aidReqMapperName, 785 aidReqMapper); 786 } else { 787 if (SAML2Utils.debug.messageEnabled()) { 788 SAML2Utils.debug.message( 789 "AssertionIDRequestUtil.getAssertionIDRequestMapper:" + 790 " got the AssertionIDRequestMapper from cache"); 791 } 792 } 793 } catch (Exception ex) { 794 SAML2Utils.debug.error( 795 "AssertionIDRequestUtil.getAssertionIDRequestMapper:", ex); 796 throw new SAML2Exception(ex); 797 } 798 799 return aidReqMapper; 800 } 801 802}