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