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 */ 028 029/* 030 * Portions Copyrighted 2013 ForgeRock, Inc 031 */ 032 033package com.sun.identity.saml2.profile; 034 035import java.io.BufferedInputStream; 036import java.io.BufferedOutputStream; 037import java.io.IOException; 038import java.io.UnsupportedEncodingException; 039import java.net.HttpURLConnection; 040import java.net.MalformedURLException; 041import java.net.URL; 042import java.security.PrivateKey; 043import java.security.cert.X509Certificate; 044import java.util.ArrayList; 045import java.util.Date; 046import java.util.Hashtable; 047import java.util.Iterator; 048import java.util.List; 049import javax.servlet.http.HttpServletRequest; 050import javax.servlet.http.HttpServletResponse; 051import javax.xml.soap.SOAPException; 052import javax.xml.soap.SOAPMessage; 053 054import com.iplanet.dpro.session.exceptions.StoreException; 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.SAML2RepositoryFactory; 066import com.sun.identity.saml2.common.SAML2Utils; 067import com.sun.identity.saml2.jaxb.entityconfig.BaseConfigType; 068import com.sun.identity.saml2.jaxb.metadata.AttributeAuthorityDescriptorElement; 069import com.sun.identity.saml2.jaxb.metadata.AssertionIDRequestServiceElement; 070import com.sun.identity.saml2.jaxb.metadata.AuthnAuthorityDescriptorElement; 071import com.sun.identity.saml2.jaxb.metadata.IDPSSODescriptorElement; 072import com.sun.identity.saml2.jaxb.metadata.RoleDescriptorType; 073import com.sun.identity.saml2.jaxb.metadata.SPSSODescriptorElement; 074import com.sun.identity.saml2.key.KeyUtil; 075import com.sun.identity.saml2.meta.SAML2MetaException; 076import com.sun.identity.saml2.meta.SAML2MetaManager; 077import com.sun.identity.saml2.plugins.AssertionIDRequestMapper; 078import com.sun.identity.saml2.protocol.AssertionIDRequest; 079import com.sun.identity.saml2.protocol.ProtocolFactory; 080import com.sun.identity.saml2.protocol.Response; 081import com.sun.identity.saml2.protocol.Status; 082import com.sun.identity.saml2.protocol.StatusCode; 083 084/** 085 * This class provides methods to send or process 086 * <code>AssertionIDRequest</code>. 087 * 088 * @supported.api 089 */ 090public class AssertionIDRequestUtil { 091 092 static KeyProvider keyProvider = KeyUtil.getKeyProviderInstance(); 093 static SAML2MetaManager metaManager = SAML2Utils.getSAML2MetaManager(); 094 static Hashtable assertionIDRequestMapperCache = new Hashtable(); 095 static final String MIME_TYPE_ASSERTION = "application/samlassertion+xml"; 096 097 private AssertionIDRequestUtil() { 098 } 099 100 /** 101 * Sends the <code>AssertionIDRequest</code> to specifiied Assertion ID 102 * Request Service and returns <code>Response</code> coming from the 103 * Assertion ID Request Service. 104 * 105 * @param assertionIDRequest the <code>AssertionIDRequest</code> object 106 * @param samlAuthorityEntityID entity ID of SAML authority 107 * @param role SAML authority role, for example, 108 * <code>SAML2Constants.ATTR_AUTH_ROLE</code>, 109 * <code>SAML2Constants.AUTHN_AUTH_ROLE</code> or 110 * <code>SAML2Constants.IDP_ROLE</code> 111 * @param realm the realm of hosted entity 112 * @param binding the binding 113 * 114 * @return the <code>Response</code> object 115 * @exception SAML2Exception if the operation is not successful 116 * 117 * @supported.api 118 */ 119 public static Response sendAssertionIDRequest( 120 AssertionIDRequest assertionIDRequest, String samlAuthorityEntityID, 121 String role, String realm, String binding) throws SAML2Exception { 122 123 StringBuffer location = new StringBuffer(); 124 RoleDescriptorType roled = getRoleDescriptorAndLocation( 125 samlAuthorityEntityID, role, realm, binding, location); 126 127 if (binding.equalsIgnoreCase(SAML2Constants.SOAP)) { 128 signAssertionIDRequest(assertionIDRequest, realm, false); 129 return sendAssertionIDRequestBySOAP(assertionIDRequest, 130 location.toString(), realm, samlAuthorityEntityID, role, roled); 131 } else { 132 throw new SAML2Exception( 133 SAML2Utils.bundle.getString("unsupportedBinding")); 134 } 135 } 136 137 /** 138 * Sends the Assertion ID to specifiied Assertion ID Request Service and 139 * returns <code>Assertion</code> coming from the Assertion ID Request 140 * Service. 141 * 142 * @param assertionID the asssertionID</code> object 143 * @param samlAuthorityEntityID entity ID of SAML authority 144 * @param role SAML authority role, for example, 145 * <code>SAML2Constants.ATTR_AUTH_ROLE</code>, 146 * <code>SAML2Constants.AUTHN_AUTH_ROLE</code> or 147 * <code>SAML2Constants.IDP_ROLE</code> 148 * @param realm the realm of hosted entity 149 * 150 * @return the <code>Assertion</code> object 151 * @exception SAML2Exception if the operation is not successful 152 * 153 * @supported.api 154 */ 155 public static Assertion sendAssertionIDRequestURI( 156 String assertionID, String samlAuthorityEntityID, 157 String role, String realm) throws SAML2Exception { 158 159 StringBuffer locationSB = new StringBuffer(); 160 getRoleDescriptorAndLocation(samlAuthorityEntityID, role, realm, 161 SAML2Constants.URI, locationSB); 162 if (locationSB.indexOf("?") == -1) { 163 locationSB.append("?"); 164 } else { 165 locationSB.append("&"); 166 } 167 locationSB.append("ID=").append(assertionID); 168 String location = fillInBasicAuthInfo(locationSB.toString(), realm, 169 samlAuthorityEntityID, role); 170 171 URL url = null; 172 try { 173 url = new URL(location); 174 } catch (MalformedURLException me) { 175 throw new SAML2Exception(me.getMessage()); 176 } 177 178 try { 179 HttpURLConnection conn = (HttpURLConnection)url.openConnection(); 180 conn.setInstanceFollowRedirects(false); 181 conn.setUseCaches(false); 182 conn.setDoOutput(false); 183 conn.connect(); 184 185 int respCode = conn.getResponseCode(); 186 if (SAML2Utils.debug.messageEnabled()) { 187 SAML2Utils.debug.message( 188 "AssertionIDRequestUtil.sendAssertionIDRequestURI: " + 189 "Response code = " + respCode + ", Response message = " + 190 conn.getResponseMessage()); 191 } 192 if (respCode != HttpURLConnection.HTTP_OK) { 193 return null; 194 } 195 196 String contentType = conn.getContentType(); 197 if (SAML2Utils.debug.messageEnabled()) { 198 SAML2Utils.debug.message( 199 "AssertionIDRequestUtil.sendAssertionIDRequestURI: " + 200 "Content type = " + contentType); 201 } 202 if ((contentType == null) || 203 (contentType.indexOf(MIME_TYPE_ASSERTION) == -1)) { 204 205 return null; 206 } 207 208 int contentLength = conn.getContentLength(); 209 if (SAML2Utils.debug.messageEnabled()) { 210 SAML2Utils.debug.message( 211 "AssertionIDRequestUtil.sendAssertionIDRequestURI: " + 212 "Content length = " + contentLength); 213 } 214 215 BufferedInputStream bin = 216 new BufferedInputStream(conn.getInputStream()); 217 StringBuffer contentSB = new StringBuffer(); 218 byte content[] = new byte[2048]; 219 220 if (contentLength != -1) { 221 int read = 0, totalRead = 0; 222 int left; 223 while (totalRead < contentLength) { 224 left = contentLength - totalRead; 225 read = bin.read(content, 0, 226 left < content.length ? left : content.length); 227 if (read == -1) { 228 // We need to close connection !! 229 break; 230 } else { 231 if (read > 0) { 232 totalRead += read; 233 contentSB.append(new String(content, 0, read)); 234 } 235 } 236 } 237 } else { 238 int numbytes; 239 int totalRead = 0; 240 241 while (true) { 242 numbytes = bin.read(content); 243 if (numbytes == -1) { 244 break; 245 } 246 247 totalRead += numbytes; 248 contentSB.append(new String(content, 0, numbytes)); 249 } 250 } 251 252 return AssertionFactory.getInstance().createAssertion( 253 contentSB.toString()); 254 } catch (IOException ioex) { 255 SAML2Utils.debug.error( 256 "AssertionIDRequest.sendAssertionIDRequestURI:", ioex); 257 throw new SAML2Exception(ioex.getMessage()); 258 } 259 } 260 261 /** 262 * Gets assertion ID from URI and returns assertion if found. 263 * 264 * @param request the <code>HttpServletRequest</code> object 265 * @param response the <code>HttpServletResponse</code> object 266 * @param samlAuthorityEntityID entity ID of SAML authority 267 * @param role SAML authority role 268 * @param realm the realm of hosted entity 269 * 270 * @exception IOException if response can't be sent 271 */ 272 public static void processAssertionIDRequestURI(HttpServletRequest request, 273 HttpServletResponse response, String samlAuthorityEntityID, 274 String role, String realm) throws IOException { 275 276 String assertionID = request.getParameter("ID"); 277 if (assertionID == null) { 278 SAMLUtils.sendError(request, response, 279 HttpServletResponse.SC_BAD_REQUEST, "nullAssertionID", 280 SAML2Utils.bundle.getString("nullAssertionID")); 281 return; 282 } 283 284 AssertionIDRequestMapper aidReqMapper = null; 285 try { 286 aidReqMapper = getAssertionIDRequestMapper(realm, 287 samlAuthorityEntityID, role); 288 } catch (SAML2Exception ex) { 289 SAMLUtils.sendError(request, response, 290 HttpServletResponse.SC_INTERNAL_SERVER_ERROR, 291 "failedToGetAssertionIDRequestMapper", ex.getMessage()); 292 return; 293 } 294 295 try { 296 aidReqMapper.authenticateRequesterURI(request, response, 297 samlAuthorityEntityID, role, realm); 298 } catch (SAML2Exception ex) { 299 SAMLUtils.sendError(request, response, 300 HttpServletResponse.SC_FORBIDDEN, 301 "failedToAuthenticateRequesterURI", ex.getMessage()); 302 return; 303 } 304 305 Assertion assertion = (Assertion)IDPCache.assertionByIDCache.get( 306 assertionID); 307 308 if ((assertion == null) || (!assertion.isTimeValid())) { 309 SAMLUtils.sendError(request, response, 310 HttpServletResponse.SC_NOT_FOUND, 311 "invalidAssertionID", 312 SAML2Utils.bundle.getString("invalidAssertionID")); 313 return; 314 } 315 316 response.setContentType(MIME_TYPE_ASSERTION); 317 response.addHeader("Cache-Control", "no-cache, no-store"); 318 response.addHeader("Pragma", "no-cache"); 319 320 String content = null; 321 try { 322 content = assertion.toXMLString(true, true); 323 } catch (SAML2Exception ex) { 324 if (SAML2Utils.debug.messageEnabled()) { 325 SAML2Utils.debug.message("AssertionIDRequestUtil." + 326 "processAssertionIDRequestURI:", ex); 327 } 328 SAMLUtils.sendError(request, response, 329 HttpServletResponse.SC_INTERNAL_SERVER_ERROR, 330 "invalidAssertion", ex.getMessage()); 331 return; 332 } 333 334 byte[] bytes = null; 335 try { 336 bytes = content.getBytes("UTF-8"); 337 } catch(UnsupportedEncodingException ueex) { 338 if (SAML2Utils.debug.messageEnabled()) { 339 SAML2Utils.debug.message("AssertionIDRequestUtil." + 340 "processAssertionIDRequestURI:", ueex); 341 } 342 SAMLUtils.sendError(request, response, 343 HttpServletResponse.SC_INTERNAL_SERVER_ERROR, 344 "unsupportedEncoding", ueex.getMessage()); 345 return; 346 } 347 response.setContentLength(bytes.length); 348 349 BufferedOutputStream bos = null; 350 try { 351 bos = new BufferedOutputStream(response.getOutputStream()); 352 bos.write(bytes, 0, bytes.length); 353 } catch (IOException ioex) { 354 SAML2Utils.debug.error("AssertionIDRequestUtil." + 355 "processAssertionIDRequestURI:", ioex); 356 } finally { 357 if (bos != null) { 358 try { 359 bos.close(); 360 } catch (IOException ioex) { 361 SAML2Utils.debug.error("AssertionIDRequestUtil." + 362 "processAssertionIDRequestURI:", ioex); 363 } 364 } 365 } 366 } 367 368 /** 369 * This method processes the <code>AssertionIDRequest</code> coming 370 * from a requester. 371 * 372 * @param assertionIDRequest the <code>AssertionIDRequest</code> object 373 * @param request the <code>HttpServletRequest</code> object 374 * @param response the <code>HttpServletResponse</code> object 375 * @param samlAuthorityEntityID entity ID of SAML authority 376 * @param role the role of SAML authority 377 * @param realm the realm of SAML authority 378 * @return the <code>Response</code> object 379 * @exception SAML2Exception if the operation is not successful 380 */ 381 public static Response processAssertionIDRequest( 382 AssertionIDRequest assertionIDRequest, HttpServletRequest request, 383 HttpServletResponse response, String samlAuthorityEntityID, 384 String role, String realm) throws SAML2Exception { 385 386 try { 387 verifyAssertionIDRequest(assertionIDRequest, samlAuthorityEntityID, 388 role, realm); 389 } catch(SAML2Exception se) { 390 SAML2Utils.debug.error("AssertionIDRequestUtil." + 391 "processAssertionIDRequest:", se); 392 return SAML2Utils.getErrorResponse(assertionIDRequest, 393 SAML2Constants.REQUESTER, null, se.getMessage(), 394 samlAuthorityEntityID); 395 } 396 397 Issuer issuer = assertionIDRequest.getIssuer(); 398 String spEntityID = issuer.getValue(); 399 400 RoleDescriptorType roled = null; 401 try { 402 if (SAML2Constants.IDP_ROLE.equals(role)) { 403 roled = metaManager.getIDPSSODescriptor(realm, 404 samlAuthorityEntityID); 405 } else if (SAML2Constants.AUTHN_AUTH_ROLE.equals(role)) { 406 roled = metaManager.getAuthnAuthorityDescriptor(realm, 407 samlAuthorityEntityID); 408 } else if (SAML2Constants.ATTR_AUTH_ROLE.equals(role)) { 409 roled = metaManager.getAttributeAuthorityDescriptor(realm, 410 samlAuthorityEntityID); 411 } 412 } catch (SAML2MetaException sme) { 413 SAML2Utils.debug.error("AssertionIDRequestUtil." + 414 "processAssertionIDRequest:", sme); 415 return SAML2Utils.getErrorResponse(assertionIDRequest, 416 SAML2Constants.RESPONDER, null, sme.getMessage(), 417 samlAuthorityEntityID); 418 } 419 420 if (roled == null) { 421 return SAML2Utils.getErrorResponse(assertionIDRequest, 422 SAML2Constants.REQUESTER, null, SAML2Utils.bundle.getString( 423 "samlAuthorityNotFound"), samlAuthorityEntityID); 424 } 425 426 List returnAssertions = null; 427 List assertionIDRefs = assertionIDRequest.getAssertionIDRefs(); 428 for(Iterator iter = assertionIDRefs.iterator(); iter.hasNext();) { 429 AssertionIDRef assertionIDRef = (AssertionIDRef)iter.next(); 430 String assertionID = assertionIDRef.getValue(); 431 432 Assertion assertion = (Assertion)IDPCache.assertionByIDCache.get( 433 assertionID); 434 if ((assertion == null) && (SAML2Utils.isSAML2FailOverEnabled())) { 435 if (SAML2Utils.debug.messageEnabled()) { 436 SAML2Utils.debug.message("AssertionIDRequestUtil." + 437 "processAssertionIDRequest: " + 438 "reading assertion from DB. ID = " + assertionID); 439 } 440 String assertionStr = null; 441 try { 442 assertionStr = 443 (String) SAML2RepositoryFactory.getInstance().retrieveSAML2Token(assertionID); 444 } catch(StoreException se) { 445 SAML2Utils.debug.error("AssertionIDRequestUtil." + 446 "processAssertionIDRequest: " + 447 "reading assertion from Repository. ID = " + assertionID + ", Operation has Failed!",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}