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