001/* 002 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 003 * 004 * Copyright (c) 2006 Sun Microsystems Inc. All Rights Reserved 005 * 006 * The contents of this file are subject to the terms 007 * of the Common Development and Distribution License 008 * (the License). You may not use this file except in 009 * compliance with the License. 010 * 011 * You can obtain a copy of the License at 012 * https://opensso.dev.java.net/public/CDDLv1.0.html or 013 * opensso/legal/CDDLv1.0.txt 014 * See the License for the specific language governing 015 * permission and limitations under the License. 016 * 017 * When distributing Covered Code, include this CDDL 018 * Header Notice in each file and include the License file 019 * at opensso/legal/CDDLv1.0.txt. 020 * If applicable, add the following below the CDDL Header, 021 * with the fields enclosed by brackets [] replaced by 022 * your own identifying information: 023 * "Portions Copyrighted [year] [name of copyright owner]" 024 * 025 * $Id: AssertionManager.java,v 1.13 2010/01/09 19:41:06 qcheng Exp $ 026 * 027 * Portions Copyrighted 2013-2016 ForgeRock AS. 028 */ 029 030package com.sun.identity.saml; 031 032import static org.forgerock.openam.utils.Time.*; 033 034import java.util.Map; 035import java.util.HashMap; 036import java.util.Date; 037import java.util.List; 038import java.util.ArrayList; 039import java.util.Set; 040import java.util.HashSet; 041import java.util.Iterator; 042import java.net.InetAddress; 043import org.w3c.dom.Element; 044import com.sun.identity.common.GeneralTaskRunnable; 045import com.sun.identity.common.PeriodicGroupRunnable; 046import com.sun.identity.common.ScheduleableGroupAction; 047import com.sun.identity.common.SystemTimerPool; 048import com.sun.identity.common.TaskRunnable; 049import com.sun.identity.common.TimerPool; 050import com.sun.identity.saml.assertion.*; 051import com.sun.identity.saml.protocol.*; 052import com.sun.identity.saml.common.*; 053import com.sun.identity.saml.plugins.*; 054import com.sun.identity.saml.xmlsig.*; 055import com.sun.identity.shared.Constants; 056import com.sun.identity.shared.DateUtils; 057import com.sun.identity.common.SystemConfigurationUtil; 058import com.sun.identity.shared.encode.Base64; 059import com.sun.identity.shared.stats.Stats; 060import com.sun.identity.shared.xml.XMLUtils; 061import java.util.StringTokenizer; 062import com.sun.identity.plugin.monitoring.FedMonAgent; 063import com.sun.identity.plugin.monitoring.FedMonSAML1Svc; 064import com.sun.identity.plugin.monitoring.MonitorManager; 065import com.sun.identity.plugin.session.SessionException; 066import com.sun.identity.plugin.session.SessionManager; 067import com.sun.identity.plugin.session.SessionProvider; 068import javax.servlet.http.HttpServletRequest; 069import javax.servlet.http.HttpServletResponse; 070 071/** 072 * The class <code>AssertionManager</code> is a <code>final</code> class 073 * that provides interfaces to create, get and destroy <code>Assertion</code>s. 074 * <p> 075 * It is a singleton class; an instance of this class can be obtained by 076 * calling <code>AssertionManager.getInstance()</code>. 077 * <p> 078 * Having obtained an instance of <code>AssertionManager</code>, its methods 079 * can be called to create/get <code>Assertion</code>, and 080 * <code>AssertionArtifact</code>, and to obtain decision from an 081 * <code>Query</code>. 082 * <p> 083 * This class could only be used in the same JVM as OpenAM. 084 * @supported.api 085 */ 086public final class AssertionManager { 087 088 // General stats class 089 public static Stats assStats; 090 public static Stats artStats; 091 092 // Assertion Statistics Class 093 private static AssertionStats assertionStats; 094 095 // Artifact Statistics Class 096 private static ArtifactStats artifactStats; 097 098 private static final String SUPER_USER = 099 "com.sun.identity.authentication.super.user"; 100 private static String superUser = null; 101 private static SessionProvider sessionProvider = null; 102 103 private static long cleanUpInterval; 104 private static long assertionTimeout; 105 private static long artifactTimeout; 106 private static long notBeforeSkew; 107 108 private static FedMonAgent agent; 109 private static FedMonSAML1Svc saml1Svc; 110 111 static { 112 assStats = Stats.getInstance("amAssertionMap"); 113 artStats = Stats.getInstance("amArtifactMap"); 114 superUser = SystemConfigurationUtil.getProperty(SUPER_USER); 115 try { 116 sessionProvider = SessionManager.getProvider(); 117 } catch (SessionException se) { 118 SAMLUtils.debug.error("Static: Couldn't get SessionProvider.", 119 se); 120 sessionProvider = null; 121 } 122 cleanUpInterval = ((Integer) SAMLServiceManager.getAttribute( 123 SAMLConstants.CLEANUP_INTERVAL_NAME)).intValue() * 1000; 124 artifactTimeout = ((Integer) SAMLServiceManager.getAttribute( 125 SAMLConstants.ARTIFACT_TIMEOUT_NAME)).intValue() * 1000; 126 assertionTimeout = ((Integer) SAMLServiceManager.getAttribute( 127 SAMLConstants.ASSERTION_TIMEOUT_NAME)).intValue() * 1000; 128 notBeforeSkew = ((Integer) SAMLServiceManager.getAttribute( 129 SAMLConstants.NOTBEFORE_TIMESKEW_NAME)).intValue() * 1000; 130 131 agent = MonitorManager.getAgent(); 132 saml1Svc = MonitorManager.getSAML1Svc(); 133 } 134 135 // Singleton instance of AssertionManager 136 private static AssertionManager instance = null; 137 138 // used to store artifact to assertionID mapping 139 private static Map artEntryMap = null; 140 // used to store assertionIDString to entry mapping 141 private static Map idEntryMap = null; 142 143 private static TaskRunnable assertionTimeoutRunnable; 144 private static TaskRunnable artifactTimeoutRunnable; 145 private static TaskRunnable goThroughRunnable; 146 147 private static String assertionVersion = null; 148 private static String protocolVersion = null; 149 150 151 private class Entry { 152 private String destID = null; 153 private String artString = null; 154 private Object token = null; 155 private Assertion assertion = null; 156 157 public Entry(Assertion assertion, String destID, String artString, 158 Object token) 159 { 160 this.assertion = assertion; 161 this.destID = destID; 162 this.artString = artString; 163 this.token = token; 164 } 165 166 public Assertion getAssertion() { 167 return assertion; 168 } 169 170 public String getDestID() { 171 return destID; 172 } 173 174 public void setDestID(String newDestID) { 175 destID = newDestID; 176 } 177 178 public String getArtifactString() { 179 return artString; 180 } 181 182 public void setArtifactString(String newArtifactString) { 183 artString = newArtifactString; 184 } 185 186 public Object getSSOToken() { 187 return token; 188 } 189 } 190 191 private class ArtEntry { 192 private String aID = null; 193 private long expiretime = 0; 194 195 public ArtEntry(String aID, long expiretime) { 196 this.aID = aID; 197 this.expiretime = expiretime; 198 } 199 200 public String getAssertionID() { 201 return aID; 202 } 203 204 public long getExpireTime() { 205 return expiretime; 206 } 207 } 208 209 /** 210 * Default Constructor 211 */ 212 private AssertionManager() { 213 idEntryMap = new HashMap(); 214 artEntryMap = new HashMap(); 215 try { 216 assertionVersion = SystemConfigurationUtil.getProperty( 217 SAMLConstants.SAML_ASSERTION_VERSION); 218 protocolVersion = SystemConfigurationUtil.getProperty( 219 SAMLConstants.SAML_PROTOCOL_VERSION); 220 } catch (Exception e) { 221 assertionVersion = SAMLConstants.ASSERTION_VERSION_1_0; 222 protocolVersion = SAMLConstants.PROTOCOL_VERSION_1_0; 223 } 224 TimerPool timerPool = SystemTimerPool.getTimerPool(); 225 ScheduleableGroupAction assertionTimeoutAction = new 226 ScheduleableGroupAction() { 227 public void doGroupAction(Object obj) { 228 deleteAssertion((String) obj, null); 229 } 230 }; 231 232 assertionTimeoutRunnable = new PeriodicGroupRunnable( 233 assertionTimeoutAction, cleanUpInterval, assertionTimeout, true); 234 timerPool.schedule(assertionTimeoutRunnable, new Date((( 235 currentTimeMillis() + cleanUpInterval) / 1000) * 1000)); 236 237 ScheduleableGroupAction artifactTimeoutAction = new 238 ScheduleableGroupAction() { 239 public void doGroupAction(Object obj) { 240 deleteAssertion(null, (String) obj); 241 } 242 }; 243 244 artifactTimeoutRunnable = new PeriodicGroupRunnable( 245 artifactTimeoutAction, cleanUpInterval, artifactTimeout, true); 246 247 timerPool.schedule(artifactTimeoutRunnable, new Date((( 248 currentTimeMillis() + cleanUpInterval) / 1000) * 1000)); 249 250 goThroughRunnable = new GoThroughRunnable(cleanUpInterval); 251 252 timerPool.schedule(goThroughRunnable, new Date((( 253 currentTimeMillis() + cleanUpInterval) / 1000) * 1000)); 254 255 if (assStats.isEnabled()) { 256 artifactStats = new ArtifactStats(artEntryMap); 257 artStats.addStatsListener(artifactStats); 258 assertionStats = new AssertionStats(idEntryMap); 259 assStats.addStatsListener(assertionStats); 260 } 261 262 } 263 264 /** 265 * Gets the singleton instance of <code>AssertionManager</code>. 266 * @return The singleton <code>AssertionManager</code> instance 267 * @throws SAMLException if unable to get the singleton 268 * <code>AssertionManager</code> instance. 269 * @supported.api 270 */ 271 public static AssertionManager getInstance() throws SAMLException { 272 // not throwing any exception 273 if (instance == null) { 274 synchronized (AssertionManager.class) { 275 if (instance == null) { 276 if (SAMLUtils.debug.messageEnabled() ) { 277 SAMLUtils.debug.message("Constructing a new instance" 278 + " of AssertionManager"); 279 } 280 instance = new AssertionManager(); 281 } 282 } 283 } 284 return instance; 285 } 286 287 /** 288 * This method creates an Assertion that contains an 289 * <code>AuthenticationStatement</code>. 290 * @param token user's session object that contains authentication 291 * information which is needed to create the 292 * <code>AuthenticationStatement</code>. 293 * @return Assertion The created Assertion. 294 * @throws SAMLException If the Assertion cannot be created. 295 * @supported.api 296 */ 297 public Assertion createAssertion(Object token) 298 throws SAMLException 299 { 300 if (assertionVersion.equals(SAMLConstants.ASSERTION_VERSION_1_0)) { 301 return createAssertion(token, null, 302 SAMLConstants.DEPRECATED_CONFIRMATION_METHOD_ARTIFACT, 0); 303 } else if(assertionVersion.equals( 304 SAMLConstants.ASSERTION_VERSION_1_1)) { 305 return createAssertion(token, null, 306 SAMLConstants.CONFIRMATION_METHOD_ARTIFACT, 1); 307 } else { 308 throw new SAMLException(SAMLUtils.bundle.getString( 309 "assertionVersionNotSupport")); 310 } 311 } 312 313 /** 314 * This method creates an Assertion that contains an 315 * <code>AuthenticationStatement</code> and 316 * an <code>AttributeStatement</code>. 317 * @param token User' session object that contains authentication 318 * information which is needed to create the 319 * <code>AuthenticationStatement</code> for the Assertion. 320 * @param attributes A list of Attribute objects which are used to 321 * create the <code>AttributeStatement</code> for the Assertion. 322 * @return Assertion The created Assertion. 323 * @throws SAMLException If the Assertion cannot be created. 324 * @supported.api 325 */ 326 public Assertion createAssertion(Object token, List attributes) 327 throws SAMLException 328 { if (assertionVersion.equals(SAMLConstants.ASSERTION_VERSION_1_0)) { 329 return createAssertion(token, attributes, 330 SAMLConstants.DEPRECATED_CONFIRMATION_METHOD_ARTIFACT, 0); 331 } else if (assertionVersion.equals( 332 SAMLConstants.ASSERTION_VERSION_1_1)) { 333 return createAssertion(token, attributes, 334 SAMLConstants.CONFIRMATION_METHOD_ARTIFACT, 1); 335 } else { 336 throw new SAMLException(SAMLUtils.bundle.getString( 337 "assertionVersionNotSupport")); 338 } 339 } 340 341 private Assertion createAssertion(Object token, List attributes, 342 String confirmationMethod, int minorVersion) 343 throws SAMLException 344 { 345 if (token == null) { 346 SAMLUtils.debug.error("AssertionManager.createAssertion(id):" 347 + "input Session is null."); 348 throw new SAMLException(SAMLUtils.bundle.getString("nullInput")); 349 } 350 if (sessionProvider == null) { 351 throw new SAMLException(SAMLUtils.bundle.getString( 352 "nullSessionProvider")); 353 } 354 String id = sessionProvider.getSessionID(token); 355 return createAssertion(id, null, null, attributes, 356 confirmationMethod, minorVersion, null); 357 } 358 359 /** 360 * This method creates an <code>AssertionArtifact</code> for the given 361 * Assertion. 362 * 363 * @param assertion The Assertion for which an Artifact needs to be created. 364 * @param destID The <code>sourceID</code> of the site for which the 365 * <code>AssertionArtifact</code> is created. It is in raw String 366 * format (not Base64 encoded, for example.) This String can be 367 * obtained from converting the 20 bytes sequence to char Array, then 368 * from the char Array to String. 369 * @return <code>AssertionArtifact</code> 370 * @throws SAMLException If the <code>AssertionArtifact</code> cannot be 371 * created. 372 * @supported.api 373 */ 374 public AssertionArtifact createAssertionArtifact(Assertion assertion, 375 String destID) 376 throws SAMLException 377 { 378 if ((assertion == null) || (destID == null) || (destID.length() == 0)) { 379 SAMLUtils.debug.error("AssertionManager.createAssertionArti" 380 + "fact(Assertion, String): null input."); 381 throw new SAMLException(SAMLUtils.bundle.getString("nullInput")); 382 } 383 384 Map partner = (Map) SAMLServiceManager.getAttribute( 385 SAMLConstants.PARTNER_URLS); 386 if ((partner == null) || (!partner.containsKey(destID))) { 387 SAMLUtils.debug.error("AssertionManager.createAssertionArtifact:" + 388 "(Assertion, String): destID not in partner list."); 389 throw new SAMLException( 390 SAMLUtils.bundle.getString("destIDNotFound")); 391 } 392 393 String handle = SAMLUtils.generateAssertionHandle(); 394 if (handle == null) { 395 SAMLUtils.debug.error("AssertionManager.createAssertion" 396 + "Artifact(Assertion,String): couldn't generate " 397 + "assertion handle."); 398 throw new SAMLResponderException( 399 SAMLUtils.bundle.getString("errorCreateArtifact")); 400 } 401 String sourceID = (String) SAMLServiceManager.getAttribute( 402 SAMLConstants.SITE_ID); 403 AssertionArtifact art = new AssertionArtifact(sourceID, handle); 404 String artString = art.getAssertionArtifact(); 405 String aID = assertion.getAssertionID(); 406 Entry entry = (Entry) idEntryMap.get(aID); 407 if ((agent != null) && agent.isRunning() && (saml1Svc != null)) { 408 saml1Svc.incSAML1Cache(FedMonSAML1Svc.ASSERTIONS, 409 FedMonSAML1Svc.CREAD); 410 } 411 if ((entry == null) && !validateNumberOfAssertions(idEntryMap)) { 412 if ((agent != null) && agent.isRunning() && (saml1Svc != null)) { 413 saml1Svc.incSAML1Cache(FedMonSAML1Svc.ASSERTIONS, 414 FedMonSAML1Svc.CMISS); 415 } 416 entry = new Entry(assertion, destID, artString, null); 417 try { 418 synchronized (idEntryMap) { 419 idEntryMap.put(aID, entry); 420 } 421 if ((agent != null) && 422 agent.isRunning() && 423 (saml1Svc != null)) 424 { 425 saml1Svc.incSAML1Cache( 426 FedMonSAML1Svc.ASSERTIONS, 427 FedMonSAML1Svc.CWRITE); 428 } 429 goThroughRunnable.addElement(aID); 430 } catch (Exception e) { 431 SAMLUtils.debug.error("AssertionManager.createAssertion" 432 + "Artifact(Assertion,String): couldn't add to " 433 + "idEntryMap." + e); 434 throw new SAMLResponderException( 435 SAMLUtils.bundle.getString("errorCreateArtifact")); 436 } 437 if (LogUtils.isAccessLoggable(java.util.logging.Level.FINER)) { 438 String[] data = {SAMLUtils.bundle.getString("assertionCreated"), 439 assertion.toString(true, true)}; 440 LogUtils.access(java.util.logging.Level.FINER, 441 LogUtils.ASSERTION_CREATED, data); 442 } else { 443 String[] data = {SAMLUtils.bundle.getString("assertionCreated"), 444 assertion.getAssertionID()}; 445 LogUtils.access(java.util.logging.Level.INFO, 446 LogUtils.ASSERTION_CREATED, data); 447 } 448 } else { 449 if ((agent != null) && agent.isRunning() && (saml1Svc != null)) { 450 saml1Svc.incSAML1Cache(FedMonSAML1Svc.ASSERTIONS, 451 FedMonSAML1Svc.CHIT); 452 } 453 String preArtString = entry.getArtifactString(); 454 if (preArtString != null) { 455 if ((agent != null) && 456 agent.isRunning() && 457 (saml1Svc != null)) 458 { 459 saml1Svc.incSAML1Cache( 460 FedMonSAML1Svc.ARTIFACTS, 461 FedMonSAML1Svc.CREAD); 462 } 463 464 if (artEntryMap.containsKey(preArtString)) { 465 if ((agent != null) && 466 agent.isRunning() && 467 (saml1Svc != null)) 468 { 469 saml1Svc.incSAML1Cache( 470 FedMonSAML1Svc.ARTIFACTS, 471 FedMonSAML1Svc.CHIT); 472 } 473 SAMLUtils.debug.error("AssertionManager.createAssertion" 474 + "Artifact(Asssertion, String): Artifact exists for " 475 + "the assertion."); 476 throw new SAMLResponderException( 477 SAMLUtils.bundle.getString("errorCreateArtifact")); 478 } else { 479 if ((agent != null) && 480 agent.isRunning() && 481 (saml1Svc != null)) 482 { 483 saml1Svc.incSAML1Cache( 484 FedMonSAML1Svc.ARTIFACTS, 485 FedMonSAML1Svc.CMISS); 486 } 487 } 488 } 489 entry.setDestID(destID); 490 entry.setArtifactString(artString); 491 } 492 // add to artEntry map 493 try { 494 Object oldEntry = null; 495 synchronized (artEntryMap) { 496 oldEntry = artEntryMap.put(artString, new 497 ArtEntry(aID, currentTimeMillis() + 498 artifactTimeout)); 499 } 500 if (oldEntry != null) { 501 artifactTimeoutRunnable.removeElement(artString); 502 } 503 artifactTimeoutRunnable.addElement(artString); 504 if ((agent != null) && agent.isRunning() && (saml1Svc != null)) { 505 saml1Svc.incSAML1Cache(FedMonSAML1Svc.ARTIFACTS, 506 FedMonSAML1Svc.CWRITE); 507 } 508 } catch (Exception e) { 509 SAMLUtils.debug.error("AssertionManager.createAssertionArt" 510 + "fact(Assertion,String): couldn't add artifact to the " 511 + "artEntryMap", e); 512 throw new SAMLResponderException( 513 SAMLUtils.bundle.getString("errorCreateArtifact")); 514 } 515 String[] data = {SAMLUtils.bundle.getString("assertionArtifactCreated"), 516 artString, aID}; 517 LogUtils.access(java.util.logging.Level.INFO, 518 LogUtils.ASSERTION_ARTIFACT_CREATED, data); 519 return art; 520 } 521 522 /** 523 * This method gets all valid Assertions managed by this 524 * <code>AssertionManager</code>. 525 * @param token User's session object which is allowed to get all 526 * Assertion. 527 * @return A Set of valid Assertion IDs. Each element in the Set is a 528 * String representing an Assertion ID. 529 * @throws SAMLException If this method can not gets all valid Assertions. 530 * @supported.api 531 */ 532 public Set getAssertions(Object token) 533 throws SAMLException 534 { 535 if (token == null) { 536 SAMLUtils.debug.error("AssertionManager.getAssertions(Object" 537 + "): input session is null."); 538 throw new SAMLException(SAMLUtils.bundle.getString("nullInput")); 539 } 540 541 if (!isSuperUser(token)) { 542 SAMLUtils.debug.error("AssertionManager.getAssertions(Object" 543 + "): Session doesn't have the privilege."); 544 throw new SAMLException(SAMLUtils.bundle.getString("noPrivilege")); 545 } 546 547 return idEntryMap.keySet(); 548 } 549 550 private boolean isSuperUser(Object token) { 551 try { 552 if (sessionProvider == null) { 553 SAMLUtils.debug.error("SessionProvider is null."); 554 return false; 555 } 556 String userID = (String) sessionProvider.getProperty(token, 557 Constants.UNIVERSAL_IDENTIFIER)[0]; 558 if (superUser != null && superUser.length() > 0) { 559 return superUser.equalsIgnoreCase(userID); 560 } 561 } catch (Exception e) { 562 if (SAMLUtils.debug.messageEnabled()) { 563 SAMLUtils.debug.message( 564 "AssertionManager.isSuperUser:Exception: ", e); 565 } 566 } 567 return false; 568 } 569 570 /** 571 * This method gets the Assertion based on the Assertion ID. 572 * @param id The Assertion ID. 573 * @return An Assertion identified by the Assertion ID. 574 * @throws SAMLException If this method can not get the Assertion. 575 */ 576 public Assertion getAssertion(String id) 577 throws SAMLException 578 { 579 if ((id == null) || (id.length() == 0)) { 580 SAMLUtils.debug.error("AssertionManager.getAssetion(String): " 581 + "id is null."); 582 throw new SAMLException(SAMLUtils.bundle.getString("nullInput")); 583 } 584 AssertionIDReference idRef = new AssertionIDReference(id); 585 return getAssertion(idRef, null, false); 586 } 587 588 /** 589 * This method gets all valid <code>AssertionArtifacts</code> 590 * managed by this <code>AssertionManager</code>. 591 * 592 * @param token User's session object which is allowed to get all 593 * <code>AssertionArtifacts</code>. 594 * @return A Set of valid <code>AssertionArtifacts</code>. Each element in 595 * the Set is an <code>AssertionArtifacts</code> object representing 596 * an artifact. 597 * @throws SAMLException If this method can not gets all valid 598 * <code>AssertionArtifacts</code>. 599 * @supported.api 600 */ 601 public Set getAssertionArtifacts(Object token) 602 throws SAMLException 603 { 604 if (token == null) { 605 SAMLUtils.debug.error("AssertionManager.getAssertionArtifacts(" + 606 "Object token): input token is null."); 607 throw new SAMLException(SAMLUtils.bundle.getString("nullInput")); 608 } 609 610 if (!isSuperUser(token)) { 611 SAMLUtils.debug.error("AssertionManager.getAssertionArtifacts(" + 612 "Object token): Session doesn't have the privilege."); 613 throw new SAMLException(SAMLUtils.bundle.getString("noPrivilege")); 614 } 615 616 return artEntryMap.keySet(); 617 } 618 619 /** 620 * Returns Assertion that contains <code>AuthenticationStatement</code>. 621 * @param id The String that contains authentication information which 622 * is needed to create the assertion. It could be a string 623 * representation of an id, a cookie, etc. 624 * @param artifact the value to be set in the SubjectConfirmation of the 625 * <code>AuthenticationStatement</code>. If it's null, 626 * <code>SubjectConfirmation</code> is set to bearer. 627 * @param destID A String that is the site the assertion is created for. 628 * @param targetUrl A URL String representing the target site 629 * @param version The relying party preferred Assertion version number. 630 * @return Assertion The created Assertion. 631 * @throws SAMLException If the Assertion cannot be created. 632 */ 633 public Assertion createSSOAssertion(String id, AssertionArtifact artifact, 634 String destID, String targetUrl, String version) 635 throws SAMLException { 636 return createSSOAssertion(id, artifact, null, null, destID, 637 targetUrl, version); 638 } 639 640 /** 641 * Returns Assertion that contains <code>AuthenticationStatement</code>. 642 * @param id The String that contains authentication information which 643 * is needed to create the assertion. It could be a string 644 * representation of an id, a cookie, etc. 645 * @param artifact the value to be set in the SubjectConfirmation of the 646 * <code>AuthenticationStatement</code>. If it's null, 647 * <code>SubjectConfirmation</code> is set to bearer. 648 * @param request The HttpServletRerquest object of the request. 649 * @param response The HttpServletResponse object. 650 * @param destID A String that is the site the assertion is created for. 651 * @param targetUrl A URL String representing the target site 652 * @param version The relying party preferred Assertion version number. 653 * @return Assertion The created Assertion. 654 * @throws SAMLException If the Assertion cannot be created. 655 */ 656 public Assertion createSSOAssertion(String id, AssertionArtifact artifact, 657 HttpServletRequest request, HttpServletResponse response, 658 String destID, String targetUrl, String version) 659 throws SAMLException 660 { 661 List attributes = null; 662 Map partnerURLs = (Map) SAMLServiceManager.getAttribute( 663 SAMLConstants.PARTNER_URLS); 664 SAMLServiceManager.SOAPEntry partnerEntry = 665 (SAMLServiceManager.SOAPEntry)partnerURLs.get(destID); 666 667 if (partnerEntry != null) { 668 try { 669 if (sessionProvider == null) { 670 throw new SAMLException(SAMLUtils.bundle.getString( 671 "nullSessionProvider")); 672 } 673 Object userSession = sessionProvider.getSession(id); 674 ConsumerSiteAttributeMapper cMapper = 675 partnerEntry.getConsumerSiteAttributeMapper(); 676 if (cMapper != null) { 677 attributes = cMapper.getAttributes(userSession, 678 request, response, targetUrl); 679 } else { 680 PartnerSiteAttributeMapper pMapper = 681 partnerEntry.getPartnerSiteAttributeMapper(); 682 if (pMapper != null) { 683 attributes = pMapper.getAttributes( 684 userSession, targetUrl); 685 } else { 686 SiteAttributeMapper mapper = 687 partnerEntry.getSiteAttributeMapper(); 688 if (mapper != null) { 689 attributes = mapper.getAttributes(userSession); 690 } 691 } 692 } 693 } catch ( SessionException ssoe) { 694 SAMLUtils.debug.error("AssertionManager.createAssertion(id):" 695 + " exception retrieving info from the Session", ssoe); 696 return null; 697 } 698 } 699 700 String nameIDFormat = request.getParameter( 701 SAMLConstants.NAME_ID_FORMAT); 702 if (artifact == null) { 703 // SAML post profile 704 if (version.equals(SAMLConstants.ASSERTION_VERSION_1_1)) { 705 // set minor version to 1 706 return createAssertion(id, artifact, destID, attributes, 707 SAMLConstants.CONFIRMATION_METHOD_BEARER, 1, nameIDFormat); 708 } else { 709 // set minor version to 0 710 return createAssertion(id, artifact, destID, attributes, 711 SAMLConstants.CONFIRMATION_METHOD_BEARER, 0, nameIDFormat); 712 } 713 } else { 714 if(version == null || version.equals( 715 SAMLConstants.ASSERTION_VERSION_1_0)) { 716 return createAssertion(id, artifact, destID, attributes, 717 SAMLConstants.DEPRECATED_CONFIRMATION_METHOD_ARTIFACT, 0, 718 nameIDFormat); 719 } else if (version.equals(SAMLConstants.ASSERTION_VERSION_1_1)) { 720 return createAssertion(id, artifact, destID, attributes, 721 SAMLConstants.CONFIRMATION_METHOD_ARTIFACT, 1, 722 nameIDFormat); 723 } else { 724 SAMLUtils.debug.error("Input version " + version + 725 " is not supported."); 726 return null; 727 } 728 } 729 } 730 731 private Assertion createAssertion(String id, AssertionArtifact artifact, 732 String destID, List attributes, String confirmationMethod, 733 int minorVersion, String nameIDFormat) throws SAMLException 734 { 735 // check input 736 if ((id == null) || (id.length() == 0)) { 737 if (SAMLUtils.debug.messageEnabled()) { 738 SAMLUtils.debug.message("AssertionManager.createAssertion(id):" 739 + "null input."); 740 } 741 throw new SAMLException(SAMLUtils.bundle.getString("nullInput")); 742 } 743 validateNumberOfAssertions(idEntryMap); 744 String authMethod = null; 745 Date authInstant = null; 746 Object token = null; 747 String clientIP = null; 748 try { 749 if (sessionProvider == null) { 750 throw new SAMLException(SAMLUtils.bundle.getString( 751 "nullSessionProvider")); 752 } 753 token = sessionProvider.getSession(id); 754 authMethod = (String) sessionProvider.getProperty( 755 token, SessionProvider.AUTH_METHOD)[0]; 756 String authSSOInstant = (String) 757 sessionProvider.getProperty(token,"authInstant")[0]; 758 if (authSSOInstant == null || authSSOInstant.equals("")) { 759 authInstant = newDate(); 760 } else { 761 authInstant = DateUtils.stringToDate(authSSOInstant); 762 } 763 764 try { 765 InetAddress clientIPAddress = 766 InetAddress.getByName(sessionProvider.getProperty( 767 token,"Host")[0]); 768 clientIP = clientIPAddress.getHostAddress(); 769 } catch (Exception e) { 770 // catching exception here since client ip is optional 771 if (SAMLUtils.debug.messageEnabled()) { 772 SAMLUtils.debug.message("AssertionManager." + 773 "createAssertion(id):" + 774 "exception when obtaining client ip: ", e); 775 } 776 } 777 } catch (Exception e) { 778 SAMLUtils.debug.error("AssertionManager." + 779 "createAssertion(id):" + 780 " exception retrieving info from the Session: ", e); 781 return null; 782 } 783 784 Map partnerURLs = 785 (Map) SAMLServiceManager.getAttribute(SAMLConstants.PARTNER_URLS); 786 SAMLServiceManager.SOAPEntry partnerEntry = 787 (SAMLServiceManager.SOAPEntry)partnerURLs.get(destID); 788 789 NameIdentifierMapper niMapper = null; 790 if (partnerEntry != null) { 791 niMapper = partnerEntry.getNameIdentifierMapper(); 792 } 793 if (niMapper == null) { 794 niMapper = new DefaultNameIdentifierMapper(); 795 } 796 797 String srcID = 798 (String)SAMLServiceManager.getAttribute(SAMLConstants.SITE_ID); 799 800 NameIdentifier ni = niMapper.getNameIdentifier(token, srcID, destID, nameIDFormat); 801 if (ni == null) { 802 SAMLUtils.debug.error("AssertionManager.createAssertion(id): " + 803 "name identifier is null."); 804 return null; 805 } 806 807 SubjectConfirmation subConfirmation = null; 808 String artString = null; 809 if ((confirmationMethod != null) && (confirmationMethod.length() > 0)) { 810 subConfirmation = new SubjectConfirmation(confirmationMethod); 811 } else { 812 if (artifact != null) { 813 if (minorVersion == 0) { 814 // set default for SAML Artifact profile 815 // here, we use SAML 1.0 confirmation method as default. 816 confirmationMethod = 817 SAMLConstants.DEPRECATED_CONFIRMATION_METHOD_ARTIFACT; 818 } else { 819 confirmationMethod = 820 SAMLConstants.CONFIRMATION_METHOD_ARTIFACT; 821 } 822 subConfirmation = new SubjectConfirmation(confirmationMethod); 823 } else { 824 // set to bearer for POST profile 825 subConfirmation = new SubjectConfirmation( 826 SAMLConstants.CONFIRMATION_METHOD_BEARER); 827 } 828 } 829 830 if (artifact != null) { 831 artString = artifact.getAssertionArtifact(); 832 } 833 Subject sub = new Subject(ni, subConfirmation); 834 SubjectLocality subjLocality = null; 835 if ((clientIP != null) && (clientIP.length() != 0)) { 836 subjLocality = new SubjectLocality(clientIP, null); 837 } 838 Set statements = new HashSet(); 839 statements.add(new AuthenticationStatement(authMethod, authInstant, 840 sub, subjLocality, null)); 841 842 if ((attributes != null) && (!attributes.isEmpty())) { 843 statements.add(new AttributeStatement(sub, attributes)); 844 } 845 Date issueInstant = newDate(); 846 Date notBefore = new Date(issueInstant.getTime() - notBeforeSkew); 847 // TODO: this period will be different for bearer 848 Date notAfter = new Date(issueInstant.getTime() + assertionTimeout); 849 Conditions cond = new Conditions(notBefore, notAfter); 850 String issuer = (String) SAMLServiceManager.getAttribute( 851 SAMLConstants.ISSUER_NAME); 852 Assertion assertion = new Assertion(null, issuer, issueInstant, cond, 853 statements); 854 assertion.setMinorVersion(minorVersion); 855 String aIDString = assertion.getAssertionID(); 856 857 // TODO:set AuthorityBinding if any 858 859 if (((Boolean) SAMLServiceManager.getAttribute( 860 SAMLConstants.SIGN_ASSERTION)).booleanValue()) 861 { 862 assertion.signXML(); 863 } 864 865 Entry entry = new Entry(assertion, destID, artString, token); 866 try { 867 Object oldEntry = null; 868 synchronized (idEntryMap) { 869 oldEntry = idEntryMap.put(aIDString, entry); 870 } 871 if (oldEntry != null) { 872 assertionTimeoutRunnable.removeElement(aIDString); 873 } 874 assertionTimeoutRunnable.addElement(aIDString); 875 if ((agent != null) && agent.isRunning() && (saml1Svc != null)) { 876 saml1Svc.incSAML1Cache(FedMonSAML1Svc.ASSERTIONS, 877 FedMonSAML1Svc.CWRITE); 878 } 879 } catch (Exception e) { 880 if (SAMLUtils.debug.messageEnabled()) { 881 SAMLUtils.debug.message("AssertionManager: couldn't add " 882 + "to idEntryMap.", e); 883 } 884 throw new SAMLResponderException( 885 SAMLUtils.bundle.getString("errorCreateAssertion")); 886 } 887 888 if (LogUtils.isAccessLoggable(java.util.logging.Level.FINER)) { 889 String[] data = { SAMLUtils.bundle.getString("assertionCreated"), 890 assertion.toString(true, true)}; 891 LogUtils.access(java.util.logging.Level.FINER, 892 LogUtils.ASSERTION_CREATED, data); 893 } else { 894 String[] data = { SAMLUtils.bundle.getString("assertionCreated"), 895 aIDString}; 896 LogUtils.access(java.util.logging.Level.INFO, 897 LogUtils.ASSERTION_CREATED, data); 898 } 899 900 if (artString != null) { 901 // put artifact in artEntryMap 902 try { 903 Object oldEntry = null; 904 synchronized (artEntryMap) { 905 oldEntry = artEntryMap.put(artString, new 906 ArtEntry(aIDString, 907 (currentTimeMillis() + artifactTimeout))); 908 } 909 if (oldEntry != null) { 910 artifactTimeoutRunnable.removeElement(artString); 911 } 912 artifactTimeoutRunnable.addElement(artString); 913 if ((agent != null) && agent.isRunning() && (saml1Svc != null)){ 914 saml1Svc.incSAML1Cache( 915 FedMonSAML1Svc.ARTIFACTS, 916 FedMonSAML1Svc.CWRITE); 917 } 918 } catch (Exception e) { 919 if (SAMLUtils.debug.messageEnabled()) { 920 SAMLUtils.debug.message("AssertionManager: couldn't add " 921 + "artifact to the artEntryMap.", e); 922 } 923 throw new SAMLResponderException( 924 SAMLUtils.bundle.getString("errorCreateArtifact")); 925 } 926 String[] data = {SAMLUtils.bundle.getString( 927 "assertionArtifactCreated"), artString, aIDString}; 928 LogUtils.access(java.util.logging.Level.INFO, 929 LogUtils.ASSERTION_ARTIFACT_CREATED, data); 930 } 931 932 if (token != null) { 933 // create a listener and add the listener to the token 934 AssertionSSOTokenListener listener = new AssertionSSOTokenListener( 935 aIDString, artString); 936 try { 937 sessionProvider.addListener(token, listener); 938 } catch (SessionException e) { 939 SAMLUtils.debug.error("AssertionManager.createAssertion(id):" 940 + " Couldn't add listener to session:", e); 941 } catch (UnsupportedOperationException uoe) { 942 SAMLUtils.debug.warning("AssertionManager.createAssertion(id):" 943 + " Operation add listener to session not supported:", 944 uoe); 945 } 946 } 947 948 return assertion; 949 } 950 951 /** 952 * Deletes an assertion from the server. This method is used by the 953 * AssertionSSOTokenListener and cleanup method in the package. 954 * @param assertionID the id of the Assertion to be deleted. 955 * @param artifact the artifact associated with this assertionID. 956 * When it's null, no artifact is associated with this assertionID. 957 */ 958 void deleteAssertion(String assertionID, String artifact) { 959 ArtEntry artEntry = null; 960 if (artifact != null) { 961 // this is the case when Session expired, and the assertion 962 // was created for artifact 963 artEntry = (ArtEntry) artEntryMap.remove(artifact); 964 String[] data = {SAMLUtils.bundle.getString( 965 "assertionArtifactRemoved"), artifact}; 966 LogUtils.access(java.util.logging.Level.FINE, 967 LogUtils.ASSERTION_ARTIFACT_REMOVED, data); 968 } 969 970 if (assertionID != null) { 971 Entry entry = null; 972 entry = (Entry) idEntryMap.remove(assertionID); 973 if (entry != null) { 974 String[] data = {SAMLUtils.bundle.getString("assertionRemoved"), 975 assertionID}; 976 LogUtils.access(java.util.logging.Level.FINE, 977 LogUtils.ASSERTION_REMOVED, data); 978 if (artifact == null) { 979 // this is the case when assertion expired, check to see 980 // if the assertion is associated with an artifact 981 String artString = entry.getArtifactString(); 982 if (artString != null) { 983 synchronized (artEntryMap) { 984 artEntryMap.remove(artString); 985 } 986 String[] data2 = {SAMLUtils.bundle.getString( 987 "assertionArtifactRemoved"), artifact}; 988 LogUtils.access(java.util.logging.Level.FINE, 989 LogUtils.ASSERTION_ARTIFACT_REMOVED, data2); 990 } 991 } 992 } 993 } else { 994 if ((artEntry != null) && SAMLServiceManager.getRemoveAssertion()) { 995 synchronized (idEntryMap) { 996 idEntryMap.remove(artEntry.getAssertionID()); 997 } 998 } 999 } 1000 } 1001 1002 /** 1003 * Gets assertion associated with the AssertionArtifact. 1004 * @param artifact An AssertionArtifact. 1005 * @param destID A Set of String that represents the destination site id. 1006 * The destination site requesting the assertion using 1007 * the artifact. This String is compared with the destID that 1008 * the artifact is created for originally. 1009 * @param destCheckFlag true if desire to match the destionation id, 1010 * otherwise it is false. If it is false, destID can 1011 * be any string, including null. 1012 * @return The Assertion referenced to by artifact. 1013 * @throws SAMLException If an error occurred during the process, or no 1014 * assertion maps to the input artifact. 1015 */ 1016 private Assertion getAssertion(AssertionArtifact artifact, Set destID, 1017 boolean destCheckFlag) 1018 throws SAMLException { 1019 if (SAMLUtils.debug.messageEnabled()) { 1020 SAMLUtils.debug.message("getAssertion(arti): destID set= " + 1021 Base64.encode(SAMLUtils.stringToByteArray( 1022 (String)destID.iterator().next()))); 1023 } 1024 // check the destination id; also if this artifact exists 1025 String artString = artifact.getAssertionArtifact(); 1026 1027 // get server id. 1028 String remoteUrl = SAMLUtils.getServerURL( 1029 artifact.getAssertionHandle()); 1030 if (remoteUrl != null) { // not this server 1031 // call AssertionManagerClient.getAssertion 1032 if (SAMLUtils.debug.messageEnabled()) { 1033 SAMLUtils.debug.message("AssertionManager.getAssertion(art, " + 1034 "destid: calling another server in lb site:" + remoteUrl); 1035 } 1036 AssertionManagerClient amc = new AssertionManagerClient( 1037 SAMLUtils.getFullServiceURL(remoteUrl)); 1038 return amc.getAssertion(artifact, destID); 1039 } // else 1040 // get the assertion ID 1041 String aIDString = null; 1042 long timeout = 0; 1043 1044 ArtEntry artEntry = (ArtEntry) artEntryMap.get(artString); 1045 if ((agent != null) && agent.isRunning() && (saml1Svc != null)) { 1046 saml1Svc.incSAML1Cache(FedMonSAML1Svc.ARTIFACTS, 1047 FedMonSAML1Svc.CREAD); 1048 } 1049 if (artEntry == null) { 1050 if ((agent != null) && agent.isRunning() && (saml1Svc != null)) { 1051 saml1Svc.incSAML1Cache(FedMonSAML1Svc.ARTIFACTS, 1052 FedMonSAML1Svc.CMISS); 1053 } 1054 if (SAMLUtils.debug.messageEnabled()) { 1055 SAMLUtils.debug.message("AssertionManager.getAssertion(art, de" 1056 + "stid): no Assertion found corresponding to artifact."); 1057 } 1058 throw new SAMLException( 1059 SAMLUtils.bundle.getString("noMatchingAssertion")); 1060 } else { 1061 if ((agent != null) && agent.isRunning() && (saml1Svc != null)) { 1062 saml1Svc.incSAML1Cache(FedMonSAML1Svc.ARTIFACTS, 1063 FedMonSAML1Svc.CHIT); 1064 } 1065 } 1066 aIDString = (String) artEntry.getAssertionID(); 1067 if (aIDString == null) { 1068 if (SAMLUtils.debug.messageEnabled()) { 1069 SAMLUtils.debug.message("AssertionManager.getAssertion(art, de" 1070 + "stid): no AssertionID found corresponding to artifact."); 1071 } 1072 throw new SAMLException( 1073 SAMLUtils.bundle.getString("noMatchingAssertion")); 1074 } 1075 1076 timeout = artEntry.getExpireTime(); 1077 if (currentTimeMillis() > timeout) { 1078 if (SAMLUtils.debug.messageEnabled()) { 1079 SAMLUtils.debug.message("AssertionManager.getAssertion(art, " 1080 + "destid): artifact timed out."); 1081 } 1082 throw new SAMLException( 1083 SAMLUtils.bundle.getString("artifactTimedOut")); 1084 } 1085 1086 Entry entry = null; 1087 entry = (Entry) idEntryMap.get(aIDString); 1088 if (entry == null) { 1089 if (SAMLUtils.debug.messageEnabled()) { 1090 SAMLUtils.debug.message("AssertionManager.getAssertion(art, de" 1091 + "stid): no Entry found corresponding to artifact."); 1092 } 1093 throw new SAMLException( 1094 SAMLUtils.bundle.getString("noMatchingAssertion")); 1095 } 1096 1097 if (destCheckFlag) { 1098 // check the destination id 1099 String dest = entry.getDestID(); 1100 if (dest == null) { 1101 if (SAMLUtils.debug.messageEnabled()) { 1102 SAMLUtils.debug.message("AssertionManager.getAssertion(" + 1103 "art, destid): no destID found corresponding to artifact."); 1104 } 1105 throw new SAMLException( 1106 SAMLUtils.bundle.getString("noDestIDMatchingArtifact")); 1107 } 1108 if (destID == null || !destID.contains(dest)) { 1109 if (SAMLUtils.debug.messageEnabled()) { 1110 SAMLUtils.debug.message("AssertionManager.getAssertion(art"+ 1111 ", destid): destinationID doesn't match."); 1112 } 1113 throw new SAMLException( 1114 SAMLUtils.bundle.getString("destIDNotMatch")); 1115 } 1116 } 1117 Assertion assertion = entry.getAssertion(); 1118 if (assertion == null) { 1119 if (SAMLUtils.debug.messageEnabled()) { 1120 SAMLUtils.debug.message("AssertionManager.getAssertion(art, de" 1121 + "stid): no Assertion found corresponding to aID."); 1122 } 1123 throw new SAMLException( 1124 SAMLUtils.bundle.getString("noMatchingAssertion")); 1125 } 1126 1127 // remove the asssertion from artEntryMap 1128 synchronized (artEntryMap) { 1129 artEntryMap.remove(artString); 1130 } 1131 artifactTimeoutRunnable.removeElement(artString); 1132 String[] data = {SAMLUtils.bundle.getString( 1133 "assertionArtifactVerified"), artString}; 1134 LogUtils.access(java.util.logging.Level.INFO, 1135 LogUtils.ASSERTION_ARTIFACT_VERIFIED, data); 1136 1137 if (SAMLServiceManager.getRemoveAssertion()) { 1138 synchronized(idEntryMap) { 1139 idEntryMap.remove(aIDString); 1140 } 1141 assertionTimeoutRunnable.removeElement(aIDString); 1142 } 1143 1144 // check the time of the assertion 1145 if (!assertion.isTimeValid()) { 1146 if (SAMLUtils.debug.messageEnabled()) { 1147 SAMLUtils.debug.message("AssertionManager: assertion " 1148 + aIDString + " is expired."); 1149 } 1150 throw new SAMLException( 1151 SAMLUtils.bundle.getString("assertionTimeNotValid")); 1152 } 1153 return assertion; 1154 } 1155 1156 /** 1157 * Gets assertion associated with the AssertionArtifact. 1158 * @param artifact An AssertionArtifact. 1159 * @param destID The destination site requesting the assertion using 1160 * the artifact. This String is compared with the destID that 1161 * the artifact is created for originally. 1162 * @return The Assertion referenced to by artifact. 1163 * @throws SAMLException If an error occurred during the process, or no 1164 * assertion maps to the input artifact. 1165 */ 1166 public Assertion getAssertion(AssertionArtifact artifact, String destID) 1167 throws SAMLException { 1168 if ((artifact == null) || destID == null || destID.length() == 0) { 1169 if (SAMLUtils.debug.messageEnabled()) { 1170 SAMLUtils.debug.message("AssertionManager: input is null."); 1171 } 1172 throw new SAMLRequesterException( 1173 SAMLUtils.bundle.getString("nullInput")); 1174 } 1175 Set destSet = new HashSet(); 1176 destSet.add(destID); 1177 return getAssertion(artifact, destSet, true); 1178 } 1179 1180 /** 1181 * Gets assertion associated with the AssertionArtifact. 1182 * @param artifact An AssertionArtifact. 1183 * @param destID A Set of String that represents the destination site id. 1184 * The destination site requesting the assertion using 1185 * the artifact. Each string in this set compares with the destID 1186 * that the artifact is created for originally. If found match, 1187 * continue the operation. Otherwise, throws error. 1188 * @return The Assertion referenced to by artifact. 1189 * @throws SAMLException If an error occurred during the process, or no 1190 * assertion maps to the input artifact. 1191 */ 1192 public Assertion getAssertion(AssertionArtifact artifact, Set destID) 1193 throws SAMLException { 1194 if ((artifact == null) || destID == null || destID.isEmpty()) { 1195 if (SAMLUtils.debug.messageEnabled()) { 1196 SAMLUtils.debug.message("AssertionManager: input is null."); 1197 } 1198 throw new SAMLRequesterException( 1199 SAMLUtils.bundle.getString("nullInput")); 1200 } 1201 return getAssertion(artifact, destID, true); 1202 } 1203 1204 /** 1205 * Gets assertion associated with the AssertionArtifact. 1206 * @param artifact An AssertionArtifact. 1207 * @return The Assertion referenced to by artifact. 1208 * @throws SAMLException If an error occurred during the process, or no 1209 * assertion maps to the input artifact. 1210 */ 1211 protected Assertion getAssertion(AssertionArtifact artifact) 1212 throws SAMLException { 1213 if ((artifact == null)) { 1214 if (SAMLUtils.debug.messageEnabled()) { 1215 SAMLUtils.debug.message("AssertionManager: input is null."); 1216 } 1217 throw new SAMLRequesterException( 1218 SAMLUtils.bundle.getString("nullInput")); 1219 } 1220 return getAssertion(artifact, null, false); 1221 } 1222 1223 /** 1224 * Gets assertion created from the query. 1225 * @param query An Assertion Query. 1226 * @param destID to whom the assertion will be created for. 1227 * @return The Assertion that is created from the query. 1228 * @throws SAMLException If the Assertion cannot be created due to an 1229 * error in the query or in the receiver. 1230 */ 1231 public Assertion getAssertion(Query query, String destID) 1232 throws SAMLException { 1233 if (query == null) { 1234 if (SAMLUtils.debug.messageEnabled()) { 1235 SAMLUtils.debug.message("AssertionManager.getAssertion: input" 1236 + " query is null."); 1237 } 1238 throw new SAMLRequesterException( 1239 SAMLUtils.bundle.getString("nullInput")); 1240 } 1241 1242 Assertion result = null; 1243 int queryType = query.getQueryType(); 1244 if (queryType == Query.AUTHENTICATION_QUERY) { 1245 result = getAuthenticationAssertion((AuthenticationQuery)query, 1246 destID); 1247 } else if (queryType == Query.AUTHORIZATION_DECISION_QUERY) { 1248 result = getAuthorizationDecisionAssertion( 1249 (AuthorizationDecisionQuery)query, destID); 1250 } else if (queryType == Query.ATTRIBUTE_QUERY) { 1251 result = getAttributeAssertion((AttributeQuery)query, destID); 1252 } else { 1253 if (SAMLUtils.debug.messageEnabled()) { 1254 SAMLUtils.debug.message("AssertionManager.getAssertion: this " 1255 + "type of query is not supported:" + queryType); 1256 } 1257 throw new SAMLRequesterException( 1258 SAMLUtils.bundle.getString("queryNotSupported")); 1259 } 1260 return result; 1261 } 1262 1263 /** 1264 * Gets assertion created from an AttributeQuery. 1265 * @param query An AttributeQuery. 1266 * @param destID to whom the assertion will be created for. Currently, 1267 * it is the <code>sourceID</code> of the site that sends the query. 1268 * @return The Assertion that is created from the query. 1269 * @throws SAMLException If the Assertion cannot be created. 1270 */ 1271 private Assertion getAttributeAssertion(AttributeQuery query, String destID) 1272 throws SAMLException 1273 { 1274 if (query == null) { 1275 // no need to log the error again 1276 return null; 1277 } 1278 1279 if ((destID == null) || (destID.length() == 0)) { 1280 if (SAMLUtils.debug.messageEnabled()) { 1281 SAMLUtils.debug.message("AssertionManager.getAttributeAssertion" 1282 + ": missing destID."); 1283 } 1284 throw new SAMLException( 1285 SAMLUtils.bundle.getString("missingDestID")); 1286 } 1287 validateNumberOfAssertions(idEntryMap); 1288 Map entries = (Map) SAMLServiceManager.getAttribute( 1289 SAMLConstants.PARTNER_URLS); 1290 if (entries == null) { 1291 if (SAMLUtils.debug.messageEnabled()) { 1292 SAMLUtils.debug.message("AssertionManager.getAttributeAssertion" 1293 + ": empty partner URL list."); 1294 } 1295 throw new SAMLException( 1296 SAMLUtils.bundle.getString("emptyPartnerURLList")); 1297 } 1298 1299 SAMLServiceManager.SOAPEntry destSite = (SAMLServiceManager.SOAPEntry) 1300 entries.get(destID); 1301 AttributeMapper attrMapper = null; 1302 if ((destSite == null) || 1303 ((attrMapper = destSite.getAttributeMapper()) == null)) 1304 { 1305 if (SAMLUtils.debug.messageEnabled()) { 1306 SAMLUtils.debug.message("AssertionManager.getAttributeAssertion" 1307 + ": couldn't obtain AttributeMapper."); 1308 } 1309 throw new SAMLException( 1310 SAMLUtils.bundle.getString("errorObtainAttributeMapper")); 1311 } 1312 1313 Subject subject = query.getSubject(); 1314 String tokenID = attrMapper.getSSOTokenID(query); 1315 Object token = null; 1316 String issuerName = (String) SAMLServiceManager.getAttribute( 1317 SAMLConstants.ISSUER_NAME); 1318 if (tokenID != null) { 1319 try { 1320 if (sessionProvider == null) { 1321 throw new SAMLException(SAMLUtils.bundle.getString( 1322 "nullSessionProvider")); 1323 } 1324 token = sessionProvider.getSession(tokenID); 1325 } catch (Exception e) { 1326 if (SAMLUtils.debug.messageEnabled()) { 1327 SAMLUtils.debug.message("AssertionManager.getAttribute" 1328 + "Assertion: invalid SSO token:", e); 1329 } 1330 throw new SAMLException( 1331 SAMLUtils.bundle.getString("invalidSSOToken")); 1332 } 1333 } else { // token is null 1334 Assertion assertion = attrMapper.getSSOAssertion(query); 1335 if (assertion == null) { 1336 if (SAMLUtils.debug.messageEnabled()) { 1337 SAMLUtils.debug.message("AssertionManager.getAttribute" 1338 + "Assertion: couldn't find SSOAssertion in query."); 1339 } 1340 throw new SAMLException( 1341 SAMLUtils.bundle.getString("noSSOAssertion")); 1342 } 1343 if (!assertion.isSignatureValid()) { 1344 if (SAMLUtils.debug.messageEnabled()) { 1345 SAMLUtils.debug.message("AssertionManager.getAttribute" 1346 + "Assertion: SSOAssertion is signature invalid."); 1347 } 1348 throw new SAMLException( 1349 SAMLUtils.bundle.getString("assertionSignatureNotValid")); 1350 } 1351 if (!assertion.isTimeValid()) { 1352 if (SAMLUtils.debug.messageEnabled()) { 1353 SAMLUtils.debug.message("AssertionManager.getAttribute" 1354 + "Assertion: SSOAssertion is time invalid."); 1355 } 1356 throw new SAMLException( 1357 SAMLUtils.bundle.getString("assertionTimeNotValid")); 1358 } 1359 Iterator iter = assertion.getStatement().iterator(); 1360 Statement statement = null; 1361 Subject ssoSubject = null; 1362 while (iter.hasNext()) { 1363 statement = (Statement) iter.next(); 1364 if (statement.getStatementType() == 1365 Statement.AUTHENTICATION_STATEMENT) 1366 { 1367 ssoSubject = ((AuthenticationStatement) statement). 1368 getSubject(); 1369 break; 1370 } 1371 } 1372 if (ssoSubject == null) { 1373 if (SAMLUtils.debug.messageEnabled()) { 1374 SAMLUtils.debug.message("AssertionManager.getAttribute" 1375 + "Assertion: missing AuthenticationStatement in " 1376 + "SSOAssertion."); 1377 } 1378 throw new SAMLException( 1379 SAMLUtils.bundle.getString("noAuthNStatement")); 1380 } 1381 String issuer = assertion.getIssuer(); 1382 String aID = assertion.getAssertionID(); 1383 if ((issuerName != null) && (issuerName.equals(issuer)) && 1384 (SAMLUtils.getServerURL(aID) == null)) 1385 { 1386 // this server is the issuer 1387 if (SAMLUtils.debug.messageEnabled()) { 1388 SAMLUtils.debug.message("AssertionManager.getAttrAssertion:" 1389 + "this server is the issuer."); 1390 } 1391 Entry entry = (Entry) idEntryMap.get(aID); 1392 if ((agent != null) && agent.isRunning() && (saml1Svc != null)){ 1393 saml1Svc.incSAML1Cache( 1394 FedMonSAML1Svc.ASSERTIONS, 1395 FedMonSAML1Svc.CREAD); 1396 } 1397 if (entry != null) { 1398 token = entry.getSSOToken(); 1399 if (token != null) { 1400 verifySSOTokenAndNI(token, 1401 ssoSubject.getNameIdentifier()); 1402 } 1403 if ((agent != null) && 1404 agent.isRunning() && 1405 (saml1Svc != null)) 1406 { 1407 saml1Svc.incSAML1Cache( 1408 FedMonSAML1Svc.ASSERTIONS, 1409 FedMonSAML1Svc.CHIT); 1410 } 1411 } else { 1412 if ((agent != null) && 1413 agent.isRunning() && 1414 (saml1Svc != null)) 1415 { 1416 saml1Svc.incSAML1Cache( 1417 FedMonSAML1Svc.ASSERTIONS, 1418 FedMonSAML1Svc.CMISS); 1419 } 1420 } 1421 } else { // this machine is not the issuer 1422 if (SAMLUtils.debug.messageEnabled()) { 1423 SAMLUtils.debug.message("AssertionManager.getAttrAssertion:" 1424 + "this server is not the issuer."); 1425 } 1426 token = checkAssertionAndCreateSSOToken(assertion, null, 1427 ssoSubject); 1428 } 1429 } 1430 1431 // get here then got a valid token 1432 List attributes = attrMapper.getAttributes(query, destID, token); 1433 if ((attributes == null) || (attributes.size() == 0)) { 1434 return null; 1435 } 1436 1437 Set stmtSet = new HashSet(); 1438 stmtSet.add(new AttributeStatement(subject, attributes)); 1439 Date issueInstant = newDate(); 1440 Date notBefore = new Date(issueInstant.getTime() - notBeforeSkew); 1441 Date notAfter = new Date(issueInstant.getTime() + assertionTimeout); 1442 Conditions cond = new Conditions(notBefore, notAfter); 1443 Assertion newAssertion = new Assertion(null, issuerName, issueInstant, 1444 cond, stmtSet); 1445 if (((Boolean) SAMLServiceManager.getAttribute( 1446 SAMLConstants.SIGN_ASSERTION)).booleanValue()) 1447 { 1448 newAssertion.signXML(); 1449 } 1450 String aIDString = newAssertion.getAssertionID(); 1451 // don't save the token and don't add listener 1452 Entry newEntry = new Entry(newAssertion, destID, null, null); 1453 1454 // add newEntry to idEntryMap 1455 try { 1456 Object oldEntry = null; 1457 synchronized (idEntryMap) { 1458 oldEntry = idEntryMap.put(aIDString, newEntry); 1459 } 1460 if (oldEntry != null) { 1461 assertionTimeoutRunnable.removeElement(aIDString); 1462 } 1463 assertionTimeoutRunnable.addElement(aIDString); 1464 if ((agent != null) && agent.isRunning() && (saml1Svc != null)) { 1465 saml1Svc.incSAML1Cache(FedMonSAML1Svc.ASSERTIONS, 1466 FedMonSAML1Svc.CWRITE); 1467 } 1468 } catch (Exception e) { 1469 if (SAMLUtils.debug.messageEnabled()) { 1470 SAMLUtils.debug.message("AssertionManager.getAttributeAssertion" 1471 + " couldn't add assertion to the idEntryMap.", e); 1472 } 1473 } 1474 1475 if (LogUtils.isAccessLoggable(java.util.logging.Level.FINER)) { 1476 String[] data = { SAMLUtils.bundle.getString("assertionCreated"), 1477 newAssertion.toString(true, true)}; 1478 LogUtils.access(java.util.logging.Level.FINER, 1479 LogUtils.ASSERTION_CREATED, data); 1480 } else { 1481 String[] data = { SAMLUtils.bundle.getString("assertionCreated"), 1482 aIDString}; 1483 LogUtils.access(java.util.logging.Level.INFO, 1484 LogUtils.ASSERTION_CREATED, data); 1485 } 1486 1487 return newAssertion; 1488 } 1489 1490 /** 1491 * Gets assertion created from an AuthenticationQuery. 1492 * @param query An AuthenticationQuery. 1493 * @param destID to whom the assertion will be created for. 1494 * @return The Assertion that is created from the query. 1495 * @throws SAMLException If the Assertion cannot be created. 1496 */ 1497 private Assertion getAuthenticationAssertion( 1498 AuthenticationQuery query, String destID) throws SAMLException 1499 { 1500 if (query == null) { 1501 // no need to log the error again 1502 return null; 1503 } 1504 validateNumberOfAssertions(idEntryMap); 1505 1506 // get the subject of the query 1507 Subject subject = query.getSubject(); 1508 1509 // get SubjectConfirmation 1510 SubjectConfirmation sc = subject.getSubjectConfirmation(); 1511 if (sc == null) { 1512 if (SAMLUtils.debug.messageEnabled()) { 1513 SAMLUtils.debug.message("AssertionManager.getAuthNAssertion:" 1514 + " missing SubjectConfirmation."); 1515 } 1516 // since we couldn't find the SSOToken in SubjectConfirmationData 1517 // we don't know if the subject is authenticated to OpenAM. 1518 throw new SAMLException( 1519 SAMLUtils.bundle.getString("missingSubjectConfirmation")); 1520 } 1521 // check ConfirmationMethod 1522 if (!SAMLUtils.isCorrectConfirmationMethod(sc)) { 1523 // don't need to log again 1524 throw new SAMLException( 1525 SAMLUtils.bundle.getString("wrongConfirmationMethodValue")); 1526 } 1527 1528 // get SubjectConfirmationData 1529 Element scData = sc.getSubjectConfirmationData(); 1530 if (scData == null) { 1531 if (SAMLUtils.debug.messageEnabled()) { 1532 SAMLUtils.debug.message("AssertionManager.getAuthNAssertion:" 1533 + " missing SubjectConfirmationData in the Subject."); 1534 } 1535 throw new SAMLException( 1536 SAMLUtils.bundle.getString("missingSubjectConfirmationData")); 1537 } 1538 1539 // SSOTokenID == scData 1540 String authMethod = null; 1541 Date authInstant = null; 1542 String nameQualifier = null; 1543 String name = null; 1544 Object token = null; 1545 String clientIP = null; 1546 try { 1547 if (sessionProvider == null) { 1548 throw new SAMLException(SAMLUtils.bundle.getString( 1549 "nullSessionProvider")); 1550 } 1551 token = sessionProvider.getSession( 1552 XMLUtils.getElementString(scData)); 1553 authMethod = SAMLServiceManager.getAuthMethodURI( 1554 sessionProvider.getProperty(token, "AuthType")[0]); 1555 // get authenticationInstant 1556 authInstant = DateUtils.stringToDate( 1557 sessionProvider.getProperty(token, "authInstant")[0]); 1558 // get the nameQualifier of the NameIdentifier 1559 nameQualifier = XMLUtils.escapeSpecialCharacters( 1560 sessionProvider.getProperty(token, "Organization")[0]); 1561 // get the name of the NameIdentifier 1562 name = XMLUtils.escapeSpecialCharacters( 1563 sessionProvider.getPrincipalName(token)); 1564 try { 1565 InetAddress clientIPAddress = 1566 InetAddress.getByName(sessionProvider.getProperty( 1567 token,"ipaddress")[0]); 1568 clientIP = clientIPAddress.getHostAddress(); 1569 } catch (Exception e) { 1570 // catching exception here since clientIP is optional 1571 if (SAMLUtils.debug.messageEnabled()) { 1572 SAMLUtils.debug.message("AssertionManager." + 1573 "getAuthNAssertion: exception when getting " + 1574 "client ip."); 1575 } 1576 } 1577 } catch (Exception e) { 1578 if (SAMLUtils.debug.messageEnabled()) { 1579 SAMLUtils.debug.message("AssertionManager.getAuthNAssertion:" 1580 + " exception retrieving info from the SSOToken:", e); 1581 } 1582 throw new SAMLException( 1583 SAMLUtils.bundle.getString("wrongSubjectConfirmationData")); 1584 } 1585 1586 // get and check NameIdentifier 1587 NameIdentifier ni = subject.getNameIdentifier(); 1588 if (ni != null) { 1589 String niName = ni.getName(); 1590 String niNameQualifier = ni.getNameQualifier(); 1591 if (((niName != null) && (!niName.equalsIgnoreCase(name))) || 1592 ((niNameQualifier != null) && 1593 (!niNameQualifier.equalsIgnoreCase(nameQualifier)))) 1594 { 1595 if (SAMLUtils.debug.messageEnabled()) { 1596 SAMLUtils.debug.message("AssertionManager.getAuthNAssertion" 1597 + ": NameIdentifier is different from info in " 1598 + "SubjectConfirmation"); 1599 } 1600 throw new SAMLException( 1601 SAMLUtils.bundle.getString("wrongNameIdentifier")); 1602 } 1603 } 1604 1605 // get and check AuthenticationMethod in the query 1606 String am = query.getAuthenticationMethod(); 1607 // check it against authMethod 1608 if ((am != null) && (am.length() != 0) && 1609 (!am.equalsIgnoreCase(authMethod))) 1610 { 1611 if (SAMLUtils.debug.messageEnabled()) { 1612 SAMLUtils.debug.message("AssertionManager.getAuthNAssertion:" 1613 + " couldn't form an assertion matching the " 1614 + "AuthenticationMethod in the query."); 1615 } 1616 throw new SAMLException(SAMLUtils.bundle.getString( 1617 "authenticationMethodInQueryNotMatch")); 1618 } 1619 SubjectLocality subjLocality = null; 1620 if ((clientIP != null) && (clientIP.length() != 0)) { 1621 subjLocality = new SubjectLocality(clientIP, null); 1622 } 1623 AuthenticationStatement statement = 1624 new AuthenticationStatement(authMethod, authInstant, subject, 1625 subjLocality, null); 1626 Date issueInstant = newDate(); 1627 // get this period from the config 1628 Date notAfter = new Date(issueInstant.getTime() + assertionTimeout); 1629 Date notBefore = new Date(issueInstant.getTime() - notBeforeSkew); 1630 Conditions cond = new Conditions(notBefore, notAfter); 1631 String issuer = (String) SAMLServiceManager.getAttribute( 1632 SAMLConstants.ISSUER_NAME); 1633 Set statements = new HashSet(); 1634 statements.add(statement); 1635 Assertion assertion = new Assertion(null, issuer, issueInstant, cond, 1636 statements); 1637 if (((Boolean) SAMLServiceManager.getAttribute( 1638 SAMLConstants.SIGN_ASSERTION)).booleanValue()) 1639 { 1640 assertion.signXML(); 1641 } 1642 String aIDString = assertion.getAssertionID(); 1643 1644 Entry entry = new Entry(assertion, destID, null, token); 1645 1646 // add entry to idEntryMap 1647 try { 1648 Object oldEntry = null; 1649 synchronized (idEntryMap) { 1650 oldEntry = idEntryMap.put(aIDString, entry); 1651 } 1652 if (oldEntry != null) { 1653 assertionTimeoutRunnable.removeElement(aIDString); 1654 } 1655 assertionTimeoutRunnable.addElement(aIDString); 1656 if ((agent != null) && agent.isRunning() && (saml1Svc != null)) { 1657 saml1Svc.incSAML1Cache(FedMonSAML1Svc.ASSERTIONS, 1658 FedMonSAML1Svc.CWRITE); 1659 } 1660 } catch (Exception e) { 1661 if (SAMLUtils.debug.messageEnabled()) { 1662 SAMLUtils.debug.message("AssertionManager.getAuthNAssertion:" 1663 + " couldn't add assertion to the idEntryMap.", e); 1664 } 1665 throw new SAMLResponderException( 1666 SAMLUtils.bundle.getString("errorCreateAssertion")); 1667 } 1668 1669 if (LogUtils.isAccessLoggable(java.util.logging.Level.FINER)) { 1670 String[] data = { SAMLUtils.bundle.getString("assertionCreated"), 1671 assertion.toString(true, true)}; 1672 LogUtils.access(java.util.logging.Level.FINER, 1673 LogUtils.ASSERTION_CREATED, data); 1674 } else { 1675 String[] data = { SAMLUtils.bundle.getString("assertionCreated"), 1676 aIDString}; 1677 LogUtils.access(java.util.logging.Level.INFO, 1678 LogUtils.ASSERTION_CREATED, data); 1679 } 1680 1681 // create a listener and add the listener to the token 1682 AssertionSSOTokenListener listener = 1683 new AssertionSSOTokenListener(aIDString); 1684 try { 1685 sessionProvider.addListener(token, listener); 1686 } catch (SessionException e) { 1687 SAMLUtils.debug.error("AssertionManager.getAuthNAssertion:" 1688 + " Couldn't add listener to token:", e); 1689 // don't need to throw an exception 1690 } 1691 1692 return assertion; 1693 } 1694 1695 /** 1696 * Gets assertion created from an AuthorizationDecisionQuery. 1697 * @param query An AuthorizationDecisionQuery. 1698 * @param destID to whom the assertion will be created for. 1699 * @return The Assertion that is created from the query. 1700 * @throws SAMLException If the Assertion cannot be created. 1701 */ 1702 private Assertion getAuthorizationDecisionAssertion( 1703 AuthorizationDecisionQuery query, String destID) 1704 throws SAMLException 1705 { 1706 return getAuthorizationDecisionAssertion(query, destID, true); 1707 } 1708 1709 /** 1710 * Gets assertion created from an AuthorizationDecisionQuery. 1711 * @param query An AuthorizationDecisionQuery. 1712 * @param destID to whom the assertion will be created for. 1713 * @param store if true, the assertion is stored internally. 1714 * @return The Assertion that is created from the query. 1715 * @throws SAMLException If the Assertion cannot be created. 1716 */ 1717 private Assertion getAuthorizationDecisionAssertion( 1718 AuthorizationDecisionQuery query, String destID, boolean store) 1719 throws SAMLException 1720 { 1721 if (query == null) { 1722 // no need to log the error again 1723 return null; 1724 } 1725 1726 if ((destID == null) || (destID.length() == 0)) { 1727 if (SAMLUtils.debug.messageEnabled()) { 1728 SAMLUtils.debug.message("AssertionManager.getAuthZAssertion: " 1729 + "missing destID."); 1730 } 1731 throw new SAMLException( 1732 SAMLUtils.bundle.getString("missingDestID")); 1733 } 1734 1735 Map entries = (Map) SAMLServiceManager.getAttribute( 1736 SAMLConstants.PARTNER_URLS); 1737 if (entries == null) { 1738 if (SAMLUtils.debug.messageEnabled()) { 1739 SAMLUtils.debug.message("AssertionManager.getAuthZAssertion: " 1740 + "empty partnerURL list."); 1741 } 1742 throw new SAMLException( 1743 SAMLUtils.bundle.getString("emptyPartnerURLList")); 1744 } 1745 1746 SAMLServiceManager.SOAPEntry destSite = (SAMLServiceManager.SOAPEntry) 1747 entries.get(destID); 1748 ActionMapper actionMapper = null; 1749 if ((destSite == null) || 1750 ((actionMapper = destSite.getActionMapper()) == null)) 1751 { 1752 if (SAMLUtils.debug.messageEnabled()) { 1753 SAMLUtils.debug.message("AssertionManager.getAuthZAssertion: " 1754 + "couldn't obtain ActionMapper."); 1755 } 1756 throw new SAMLException( 1757 SAMLUtils.bundle.getString("errorObtainActionMapper")); 1758 } 1759 1760 Subject querySubject = query.getSubject(); 1761 NameIdentifier queryNI = querySubject.getNameIdentifier(); 1762 Object token = null; 1763 boolean existingToken = true; 1764 1765 String tokenID = actionMapper.getSSOTokenID(query); 1766 if (tokenID != null) { 1767 // if there is a token, then the token must be valid 1768 try { 1769 if (sessionProvider == null) { 1770 throw new SAMLException(SAMLUtils.bundle.getString( 1771 "nullSessionProvider")); 1772 } 1773 token = sessionProvider.getSession(tokenID); 1774 } catch (Exception e) { 1775 if (SAMLUtils.debug.messageEnabled()) { 1776 SAMLUtils.debug.message("AssertionManager.getAuthZAssertion" 1777 + ": invalid SSO token:", e); 1778 } 1779 throw new SAMLException( 1780 SAMLUtils.bundle.getString("invalidSSOToken")); 1781 } 1782 verifySSOTokenAndNI(token, queryNI); 1783 } else { 1784 Assertion assertion = actionMapper.getSSOAssertion(query, destID); 1785 if (assertion != null) { 1786 // if there is an assertion, then it must be valid 1787 Map tokenMap = verifyAssertionAndGetSSOToken(querySubject, 1788 assertion); 1789 token = (Object) tokenMap.get("true"); 1790 if (token == null){ 1791 existingToken = false; 1792 token = (Object) tokenMap.get("false"); 1793 } 1794 } 1795 } 1796 1797 if (token == null) { 1798 if (SAMLUtils.debug.messageEnabled()) { 1799 SAMLUtils.debug.message("AssertionManager.getAuthZAssertion: " 1800 + "Couldn't obtain ssotoken."); 1801 } 1802 throw new SAMLException( 1803 SAMLUtils.bundle.getString("cannotVerifySubject")); 1804 } 1805 1806 Map map = actionMapper.getAuthorizationDecisions(query, token, destID); 1807 1808 // no need to invalidate the newly created ssotoken since the token 1809 // will be invalidated/destroyed when the short maxSessionTime and 1810 // maxIdleTime are reached. 1811 return getAuthorizationDecisionAssertion(query, destID, true, 1812 token, existingToken, map); 1813 } 1814 1815 private Map verifyAssertionAndGetSSOToken(Subject querySubject, 1816 Assertion assertion) 1817 throws SAMLException 1818 { 1819 if ((querySubject == null) || (assertion == null)) { 1820 if (SAMLUtils.debug.messageEnabled()) { 1821 SAMLUtils.debug.message("AssertionManager.verifyAssertionAnd" 1822 + "GetSSOToken: null input."); 1823 } 1824 throw new SAMLException( 1825 SAMLUtils.bundle.getString("cannotVerifySubject")); 1826 } 1827 1828 if (!assertion.isSignatureValid()) { 1829 if (SAMLUtils.debug.messageEnabled()) { 1830 SAMLUtils.debug.message("AssertionManager.verifyAssertionAnd" 1831 + "GetSSOToken: SSOAssertion is signature invalid."); 1832 } 1833 throw new SAMLException( 1834 SAMLUtils.bundle.getString("assertionSignatureNotValid")); 1835 } 1836 if (!assertion.isTimeValid()) { 1837 if (SAMLUtils.debug.messageEnabled()) { 1838 SAMLUtils.debug.message("AssertionManager.verifyAssertionAnd" 1839 + "GetSSOToken: SSOAssertion is time invalid."); 1840 } 1841 throw new SAMLException( 1842 SAMLUtils.bundle.getString("assertionTimeNotValid")); 1843 } 1844 1845 // TODO: check AudienceRestrictionConditions if any 1846 1847 Map tokenMap = new HashMap(); 1848 Object token = null; 1849 String issuerName = (String) SAMLServiceManager.getAttribute( 1850 SAMLConstants.ISSUER_NAME); 1851 String issuer = assertion.getIssuer(); 1852 String aID = assertion.getAssertionID(); 1853 if ((issuerName != null) && (issuerName.equals(issuer)) && 1854 (SAMLUtils.getServerURL(aID) == null)) 1855 { 1856 // this server is the issuer 1857 if (SAMLUtils.debug.messageEnabled()) { 1858 SAMLUtils.debug.message("AssertionManager.getAuthZAssertion:" 1859 + "this server is the issuer."); 1860 } 1861 if ((agent != null) && agent.isRunning() && (saml1Svc != null)) { 1862 saml1Svc.incSAML1Cache(FedMonSAML1Svc.ASSERTIONS, 1863 FedMonSAML1Svc.CREAD); 1864 } 1865 Entry entry = (Entry) idEntryMap.get(aID); 1866 if (entry != null) { 1867 if ((agent != null) && agent.isRunning() && (saml1Svc != null)){ 1868 saml1Svc.incSAML1Cache( 1869 FedMonSAML1Svc.ASSERTIONS, 1870 FedMonSAML1Svc.CHIT); 1871 } 1872 token = entry.getSSOToken(); 1873 if (token != null) { 1874 verifySSOTokenAndNI(token, 1875 querySubject.getNameIdentifier()); 1876 tokenMap.put("true", token); 1877 return tokenMap; 1878 } 1879 } else { 1880 if ((agent != null) && agent.isRunning() && (saml1Svc != null)){ 1881 saml1Svc.incSAML1Cache( 1882 FedMonSAML1Svc.ASSERTIONS, 1883 FedMonSAML1Svc.CMISS); 1884 } 1885 } 1886 1887 if (SAMLUtils.debug.messageEnabled()) { 1888 SAMLUtils.debug.message("AssertionManager.verifyAssertionAnd" 1889 + "GetSSOToken: either not an AuthN assertion or token " 1890 + "is not for this subject."); 1891 } 1892 throw new SAMLException(SAMLUtils.bundle. 1893 getString("cannotVerifySubject")); 1894 } else { 1895 if (SAMLUtils.debug.messageEnabled()) { 1896 SAMLUtils.debug.message("AssertionManager.getAuthZAssertion:" 1897 + "this server is not the issuer."); 1898 } 1899 Iterator iter = assertion.getStatement().iterator(); 1900 Statement statement = null; 1901 AuthenticationStatement ssoStatement = null; 1902 while (iter.hasNext()) { 1903 statement = (Statement) iter.next(); 1904 if (statement.getStatementType() == 1905 Statement.AUTHENTICATION_STATEMENT) 1906 { 1907 ssoStatement = (AuthenticationStatement) statement; 1908 break; 1909 } 1910 } 1911 if (ssoStatement == null) { 1912 if (SAMLUtils.debug.messageEnabled()) { 1913 SAMLUtils.debug.message("AssertionManager.verifyAssertion" 1914 + "AndGetSSOToken: missing AuthenticationStatement in " 1915 + "SSOAssertion."); 1916 } 1917 throw new SAMLException( 1918 SAMLUtils.bundle.getString("noAuthNStatement")); 1919 } 1920 1921 token = checkAssertionAndCreateSSOToken(assertion, 1922 (AuthenticationStatement)statement, querySubject); 1923 tokenMap.put("false", token); 1924 } 1925 return tokenMap; 1926 } 1927 1928 private void verifySSOTokenAndNI(Object token, NameIdentifier ni) 1929 throws SAMLException 1930 { 1931 String name = null; 1932 String nameQualifier = null; 1933 try { 1934 if (sessionProvider == null) { 1935 throw new SAMLException(SAMLUtils.bundle.getString( 1936 "nullSessionProvider")); 1937 } 1938 name = XMLUtils.escapeSpecialCharacters( 1939 sessionProvider.getPrincipalName(token)); 1940 nameQualifier = XMLUtils.escapeSpecialCharacters( 1941 sessionProvider.getProperty(token, "Organization")[0]); 1942 } catch (Exception e) { 1943 if (SAMLUtils.debug.messageEnabled()) { 1944 SAMLUtils.debug.message("AssertionManager.verifySSOTokenAndNI: " 1945 + "Session is not valid.", e); 1946 } 1947 throw new SAMLException( 1948 SAMLUtils.bundle.getString("cannotVerifySubject")); 1949 } 1950 1951 if (ni == null) { 1952 return; 1953 } 1954 1955 String niName = ni.getName(); 1956 String niNameQualifier = ni.getNameQualifier(); 1957 if (((niName != null) && (!niName.equalsIgnoreCase(name))) || 1958 ((niNameQualifier != null) && (!niNameQualifier. 1959 equalsIgnoreCase(nameQualifier)))) 1960 { 1961 if (SAMLUtils.debug.messageEnabled()) { 1962 SAMLUtils.debug.message("AssertionManager.verifySSOToken" 1963 + "AndNI: NameIdentifier is different from info in " 1964 + "token."); 1965 } 1966 throw new SAMLException(SAMLUtils.bundle. 1967 getString("wrongNameIdentifier")); 1968 } 1969 } 1970 1971 private Object checkAssertionAndCreateSSOToken(Assertion assertion, 1972 AuthenticationStatement statement, Subject subject) 1973 throws SAMLException 1974 { 1975 // check if issuer is on our list. 1976 String issuer = assertion.getIssuer(); 1977 SAMLServiceManager.SOAPEntry sourceSite = 1978 SAMLUtils.getSourceSite(issuer); 1979 if (sourceSite == null) { 1980 if (SAMLUtils.debug.messageEnabled()) { 1981 SAMLUtils.debug.message("AssertionManager.checkAssertionAnd" 1982 + "CreateSSOToken: issuer is not on the partnerURL list."); 1983 } 1984 throw new SAMLException(SAMLUtils.bundle. 1985 getString("cannotVerifySubject")); 1986 } 1987 1988 // TODO: check AudienceRestrictionCondition if any 1989 1990 if (statement != null) { 1991 // check the subject 1992 if ((subject == null) || (!subject.equals(statement.getSubject()))) 1993 { 1994 if (SAMLUtils.debug.messageEnabled()) { 1995 SAMLUtils.debug.message("AssertionManager.verifyAndGetSSO" 1996 + "Token: wrong subject in evidence."); 1997 } 1998 throw new SAMLException(SAMLUtils.bundle. 1999 getString("cannotVerifySubject")); 2000 } 2001 } 2002 return createTempSSOToken(assertion, subject, sourceSite); 2003 } 2004 2005 private Object createTempSSOToken(Assertion assertion, Subject subject, 2006 SAMLServiceManager.SOAPEntry sourceSite) 2007 throws SAMLException 2008 { 2009 List assertions = new ArrayList(); 2010 assertions.add(assertion); 2011 String srcID = sourceSite.getSourceID(); 2012 String name = null; 2013 String org = null; 2014 2015 PartnerAccountMapper paMapper = sourceSite.getPartnerAccountMapper(); 2016 if (paMapper != null) { 2017 Map map = paMapper.getUser(assertions, srcID, null); 2018 name = (String) map.get(PartnerAccountMapper.NAME); 2019 org = (String) map.get(PartnerAccountMapper.ORG); 2020 } 2021 2022 if ((org == null) || (name == null)) { 2023 if (SAMLUtils.debug.messageEnabled()) { 2024 SAMLUtils.debug.message("AssertionManager." + 2025 "createTempSSOToken: couldn't map the subject " + 2026 "to a local user."); 2027 } 2028 throw new SAMLRequesterException( 2029 SAMLUtils.bundle.getString("cannotMapSubject")); 2030 } else { 2031 if (SAMLUtils.debug.messageEnabled()) { 2032 SAMLUtils.debug.message("AssertionManager." + 2033 "createTempSSOToken: org = " + org + ", name = " + 2034 name); 2035 } 2036 } 2037 2038 Object token = null; 2039 try { 2040 Map infoMap = new HashMap(); 2041 if ((org != null) && (org.length() != 0)) { 2042 infoMap.put(SessionProvider.REALM, org); 2043 } else { 2044 infoMap.put(SessionProvider.REALM, "/"); 2045 } 2046 infoMap.put(SessionProvider.PRINCIPAL_NAME, name); 2047 infoMap.put(SessionProvider.AUTH_LEVEL, "0"); 2048 token = SAMLUtils.generateSession(null, null, infoMap); 2049 } catch (Exception e) { 2050 if (SAMLUtils.debug.messageEnabled()) { 2051 SAMLUtils.debug.message("AssertionManger." + 2052 "createTempSSOToken: Couldn't retrieve " + 2053 "the ssotoken.", e); 2054 } 2055 throw new SAMLResponderException( 2056 SAMLUtils.bundle.getString("errorCreateAssertion")); 2057 } 2058 return token; 2059 } 2060 2061 /** 2062 * @param addListener A listener to the single sign on token is added only 2063 * when both store and addListener are true. 2064 */ 2065 private Assertion getAuthorizationDecisionAssertion( 2066 AuthorizationDecisionQuery query, String destID, 2067 boolean store, Object token, 2068 boolean addListener, Map actionMap) 2069 throws SAMLException 2070 { 2071 if (actionMap == null) { 2072 if (SAMLUtils.debug.messageEnabled()) { 2073 SAMLUtils.debug.message("AssertionManager.getAuthZAssertion: " 2074 + "actionMap from ActionMapper is null."); 2075 } 2076 throw new SAMLException( 2077 SAMLUtils.bundle.getString("nullAuthZDecision")); 2078 } 2079 2080 validateNumberOfAssertions(idEntryMap); 2081 int decision; 2082 List newActions = null; 2083 if ((newActions = (List) actionMap.get(ActionMapper.PERMIT)) != null) { 2084 decision = AuthorizationDecisionStatement.DecisionType.PERMIT; 2085 } else if ((newActions = (List) actionMap.get(ActionMapper.DENY)) 2086 != null) 2087 { 2088 decision = AuthorizationDecisionStatement.DecisionType.DENY; 2089 } else { 2090 newActions = (List) actionMap.get(ActionMapper.INDETERMINATE); 2091 if (newActions == null) { 2092 // try not to be too restrictive 2093 newActions = query.getAction(); 2094 } 2095 decision = 2096 AuthorizationDecisionStatement.DecisionType.INDETERMINATE; 2097 } 2098 2099 //create statement 2100 AuthorizationDecisionStatement statement = 2101 new AuthorizationDecisionStatement( 2102 query.getSubject(), query.getResource(), decision, 2103 newActions, query.getEvidence()); 2104 2105 Date issueInstant = newDate(); 2106 Date notAfter = new Date(issueInstant.getTime() + assertionTimeout); 2107 Date notBefore = new Date(issueInstant.getTime() - notBeforeSkew); 2108 Conditions cond = new Conditions(notBefore, notAfter); 2109 String issuer = (String) SAMLServiceManager.getAttribute( 2110 SAMLConstants.ISSUER_NAME); 2111 Set statements = new HashSet(); 2112 statements.add(statement); 2113 Assertion assertion = new Assertion(null, issuer, issueInstant, cond, 2114 statements); 2115 if (((Boolean) SAMLServiceManager.getAttribute( 2116 SAMLConstants.SIGN_ASSERTION)).booleanValue()) 2117 { 2118 assertion.signXML(); 2119 } 2120 String aIDString = assertion.getAssertionID(); 2121 2122 if (store) { 2123 Entry entry = null; 2124 if (addListener) { 2125 // create a listener and add the listener to the token 2126 AssertionSSOTokenListener listener = 2127 new AssertionSSOTokenListener(aIDString); 2128 try { 2129 if (sessionProvider == null) { 2130 throw new SAMLException(SAMLUtils.bundle. 2131 getString("nullSessionProvider")); 2132 } 2133 sessionProvider.addListener(token, listener); 2134 } catch (SessionException e) { 2135 SAMLUtils.debug.error("AssertionManager.getAuthNAssertion:" 2136 + " Couldn't get listener to token:", e); 2137 // don't need to throw an exception 2138 } 2139 } 2140 entry = new Entry(assertion, destID, null, null); 2141 2142 // put assertion in idEntryMap 2143 try { 2144 Object oldEntry = null; 2145 synchronized (idEntryMap) { 2146 oldEntry = idEntryMap.put(aIDString, entry); 2147 } 2148 if (oldEntry != null) { 2149 assertionTimeoutRunnable.removeElement(aIDString); 2150 } 2151 assertionTimeoutRunnable.addElement(aIDString); 2152 if ((agent != null) && agent.isRunning() && (saml1Svc != null)){ 2153 saml1Svc.incSAML1Cache( 2154 FedMonSAML1Svc.ASSERTIONS, 2155 FedMonSAML1Svc.CWRITE); 2156 } 2157 } catch (Exception e) { 2158 if (SAMLUtils.debug.messageEnabled()) { 2159 SAMLUtils.debug.message("AssertionManager.getAuthZAssertion" 2160 + ": couldn't add assertion to the idAssertionMap.", e); 2161 } 2162 throw new SAMLResponderException( 2163 SAMLUtils.bundle.getString("errorCreateAssertion")); 2164 } 2165 2166 if (LogUtils.isAccessLoggable(java.util.logging.Level.FINER)) { 2167 String[] data = {SAMLUtils.bundle.getString("assertionCreated"), 2168 assertion.toString(true, true)}; 2169 LogUtils.access(java.util.logging.Level.FINER, 2170 LogUtils.ASSERTION_CREATED, data); 2171 } else { 2172 String[] data = {SAMLUtils.bundle.getString("assertionCreated"), 2173 aIDString}; 2174 LogUtils.access(java.util.logging.Level.INFO, 2175 LogUtils.ASSERTION_CREATED, data); 2176 } 2177 } 2178 2179 return assertion; 2180 } 2181 2182 /** 2183 * Gets the Assertion referenced by an <code>AssertionIDReference</code>. 2184 * @param idRef The <code>AssertionIDReference</code> which references to an 2185 * Assertion. 2186 * @return the Assertion referenced by the <code>AsertionIDReference</code>. 2187 * @throws SAMLException If an error occurred during the process; or 2188 * the assertion could not be found. 2189 */ 2190 public Assertion getAssertion(AssertionIDReference idRef) 2191 throws SAMLException 2192 { 2193 return getAssertion(idRef, null, false); 2194 } 2195 2196 /** 2197 * Gets the Assertion referenced by an <code>AssertionIDReference</code>. 2198 * This method is usually used after the call 2199 * <code>AssertionManager.getAssertions(SSOToken)</code>. 2200 * The assertion is retrieved from this <code>AssertionManager</code> only. 2201 * @param idRef The <code>AssertionIDReference</code> which references to an 2202 * Assertion. 2203 * @param token Use's session object that is allowed to obtain the 2204 * assertion. This token must have top level administrator role. 2205 * @return the Assertion referenced by the <code>AsertionIDReference</code>. 2206 * @throws SAMLException If an error occurred during the process; the token 2207 * does not have the privilege; or the assertion could not be 2208 * found. 2209 * @supported.api 2210 */ 2211 public Assertion getAssertion(AssertionIDReference idRef, Object token) 2212 throws SAMLException { 2213 if (token == null) { 2214 SAMLUtils.debug.error("AssertionManager.getAssertion(idRef, token" 2215 + "): input token is null."); 2216 throw new SAMLException(SAMLUtils.bundle.getString("nullInput")); 2217 } 2218 2219 if (!isSuperUser(token)) { 2220 SAMLUtils.debug.error("AssertionManager.getAssertion(idRef, token" 2221 + "): Session doesn't have the privilege."); 2222 throw new SAMLException(SAMLUtils.bundle.getString("noPrivilege")); 2223 } 2224 return getAssertion(idRef, null, true); 2225 } 2226 2227 /** 2228 * Gets the Assertion referenced by an <code>AssertionIDReference</code>. 2229 * @param idRef The <code>AssertionIDReference</code> which references to an 2230 * Assertion. 2231 * @param destID The destination site id requesting the assertion using 2232 * the assertion id reference. This String is compared with the 2233 * <code>destID</code> that the assertion is created for originally. 2234 * This field is not used (could be null) if the assertion was 2235 * created without a <code>destID</code> originally. This String can 2236 * be obtained from converting the 20 byte site id sequence to char 2237 * array, then a new String from the char array. 2238 * @return the Assertion referenced by the <code>AsertionIDReference</code>. 2239 * @throws SAMLException If an error occurred during the process; or 2240 * the assertion could not be found. 2241 * @supported.api 2242 */ 2243 public Assertion getAssertion(AssertionIDReference idRef, String destID) 2244 throws SAMLException { 2245 if (destID == null) { 2246 return getAssertion(idRef, null, false); 2247 } else { 2248 Set destSet = new HashSet(); 2249 destSet.add(destID); 2250 return getAssertion(idRef, destSet, false); 2251 } 2252 } 2253 2254 /** 2255 * Gets the Assertion referenced by an <code>AssertionIDReference</code>. 2256 * @param idRef The <code>AssertionIDReference</code> which references to an 2257 * Assertion. 2258 * @param destID A Set of destination site id. The destination site id 2259 * requesting the assertion using the assertion id reference. 2260 * This String is compared with the <code>destID</code> that the 2261 * assertion is created for originally. This field is not used 2262 * (could be null) if the assertion was created without a 2263 * <code>destID</code> originally. This String can be obtained from 2264 * converting the 20 byte site id sequence to char array, then a new 2265 * String from the char array. 2266 * @return the Assertion referenced by the <code>AsertionIDReference</code>. 2267 * @throws SAMLException If an error occurred during the process; or 2268 * the assertion could not be found. 2269 * @supported.api 2270 */ 2271 public Assertion getAssertion(AssertionIDReference idRef, Set destID) 2272 throws SAMLException { 2273 return getAssertion(idRef, destID, false); 2274 } 2275 2276 /** 2277 * Gets the Assertion referenced by an <code>AssertionIDReference</code>. 2278 * @param id The <code>AssertionIDReference</code> which references to an 2279 * Assertion. 2280 * @param destID A Set of String that represents the destination id. 2281 * The destination site id requesting the assertion using 2282 * the assertion id reference. This String is compared with the 2283 * <code>destID</code> that the assertion is created for originally. 2284 * This field is not used (could be null) if the assertion was 2285 * created without a <code>destID</code> originally. This String can 2286 * be obtained from converting the 20 byte site id sequence to char 2287 * array, then a new String from the char array. 2288 * @param useToken A boolean value. If set to true, destID is not 2289 * checked against with the string that the assertion is created 2290 * for originallyr, the assertion is retrieved from this server 2291 * only. 2292 * @return the Assertion referenced by the <code>AsertionIDReference</code>. 2293 * @throws SAMLException If an error occurred during the process; or 2294 * the assertion could not be found. 2295 */ 2296 private Assertion getAssertion(AssertionIDReference idRef, Set destID, 2297 boolean useToken) 2298 throws SAMLException { 2299 if (SAMLUtils.debug.messageEnabled()) { 2300 SAMLUtils.debug.message("getAssertion(idRef): destID set=" + 2301 destID); 2302 } 2303 if (idRef == null) { 2304 if (SAMLUtils.debug.messageEnabled()) { 2305 SAMLUtils.debug.message("AssertionManager.getAssertion(Asser" 2306 + "tionIDRef): null AssertionID."); 2307 } 2308 throw new SAMLRequesterException( 2309 SAMLUtils.bundle.getString("nullInput")); 2310 } 2311 String aIDString = idRef.getAssertionIDReference(); 2312 if (!useToken) { 2313 // get server id. 2314 String remoteUrl = SAMLUtils.getServerURL(aIDString); 2315 if (remoteUrl != null) { // not this server 2316 // call AssertionManagerClient.getAssertion 2317 if (SAMLUtils.debug.messageEnabled()) { 2318 SAMLUtils.debug.message("AssertionManager." + 2319 "getAssertion(idRef): calling another server" + 2320 " in lb site:" + remoteUrl); 2321 } 2322 AssertionManagerClient amc = new AssertionManagerClient( 2323 SAMLUtils.getFullServiceURL(remoteUrl)); 2324 return amc.getAssertion(idRef, destID); 2325 } //else 2326 } 2327 2328 Entry entry = (Entry) idEntryMap.get(aIDString); 2329 if ((agent != null) && agent.isRunning() && (saml1Svc != null)) { 2330 saml1Svc.incSAML1Cache(FedMonSAML1Svc.ASSERTIONS, 2331 FedMonSAML1Svc.CREAD); 2332 } 2333 if (entry == null) { 2334 if ((agent != null) && agent.isRunning() && (saml1Svc != null)) { 2335 saml1Svc.incSAML1Cache(FedMonSAML1Svc.ASSERTIONS, 2336 FedMonSAML1Svc.CMISS); 2337 } 2338 if (SAMLUtils.debug.messageEnabled()) { 2339 SAMLUtils.debug.message("AssertionManager.getAssertion(Asser" 2340 + "tionIDRef): no matching assertion found in idEntryMap."); 2341 } 2342 throw new SAMLException( 2343 SAMLUtils.bundle.getString("noMatchingAssertion")); 2344 } else { 2345 if ((agent != null) && agent.isRunning() && (saml1Svc != null)) { 2346 saml1Svc.incSAML1Cache(FedMonSAML1Svc.ASSERTIONS, 2347 FedMonSAML1Svc.CHIT); 2348 } 2349 } 2350 2351 Assertion assertion = entry.getAssertion(); 2352 if (assertion == null) { 2353 if (SAMLUtils.debug.messageEnabled()) { 2354 SAMLUtils.debug.message("AssertionManager.getAssertion(" 2355 + "AssertionIDRef): no matching assertion found."); 2356 } 2357 throw new SAMLException( 2358 SAMLUtils.bundle.getString("noMatchingAssertion")); 2359 } 2360 2361 if (!useToken) { 2362 // check if the destID is correct 2363 String dest = entry.getDestID(); 2364 if (dest != null) { 2365 if ((destID == null) || (!destID.contains(dest))) { 2366 if (SAMLUtils.debug.messageEnabled()) { 2367 SAMLUtils.debug.message("AssertionManager.getAssertion(" 2368 + "AssertionID): destID doesn't match."); 2369 } 2370 throw new SAMLException( 2371 SAMLUtils.bundle.getString("destIDNotMatch")); 2372 } 2373 } 2374 } 2375 2376 // check the time of the assertion 2377 if (!assertion.isTimeValid()) { 2378 if (SAMLUtils.debug.messageEnabled()) { 2379 SAMLUtils.debug.message("AssertionManager: assertion " 2380 + aIDString + " is expired."); 2381 } 2382 throw new SAMLException("assertionTimeNotValid"); 2383 } 2384 2385 return assertion; 2386 } 2387 2388 /** 2389 * Creates an AssertionArtifact. 2390 * @param id The String that contains authentication information which 2391 * is needed to create the assertion. It could be a string 2392 * representation of an id, a cookie, etc. 2393 * @param destID The destination site that the artifact is created for. 2394 * @return The AssertionArtifact. 2395 * @throws SAMLException If the AssertionArtifact cannot be created. 2396 */ 2397 public AssertionArtifact createAssertionArtifact(String id, 2398 String destID) throws SAMLException { 2399 return createAssertionArtifact(id, destID, null, null); 2400 } 2401 /** 2402 * Creates an AssertionArtifact. 2403 * @param id The String that contains authentication information which 2404 * is needed to create the assertion. It could be a string 2405 * representation of an id, a cookie, etc. 2406 * @param destID The destination site that the artifact is created for. 2407 * @param targetUrl A URL String representing the target site 2408 * @param version The relying party preferred Assertion version number. 2409 * @return The AssertionArtifact. 2410 * @throws SAMLException If the AssertionArtifact cannot be created. 2411 */ 2412 public AssertionArtifact createAssertionArtifact(String id, 2413 String destID, String targetUrl, 2414 String version) 2415 throws SAMLException { 2416 return createAssertionArtifact(id, destID, null, null, 2417 targetUrl, version); 2418 } 2419 /** 2420 * Creates an AssertionArtifact. 2421 * @param id The String that contains authentication information which 2422 * is needed to create the assertion. It could be a string 2423 * representation of an id, a cookie, etc. 2424 * @param destID The destination site that the artifact is created for. 2425 * @param request The HttpServletRerquest object of the request. 2426 * @param response The HttpServletResponse object. 2427 * @param targetUrl A URL String representing the target site 2428 * @param version The relying party preferred Assertion version number. 2429 * @return The AssertionArtifact. 2430 * @throws SAMLException If the AssertionArtifact cannot be created. 2431 */ 2432 public AssertionArtifact createAssertionArtifact(String id, 2433 String destID, HttpServletRequest request, 2434 HttpServletResponse response, String targetUrl, 2435 String version) throws SAMLException { 2436 // check input 2437 if ((id == null) || (destID == null)) { 2438 if (SAMLUtils.debug.messageEnabled()) { 2439 SAMLUtils.debug.message("AssertionManager: null input for" 2440 + " method createAssertionArtifact."); 2441 } 2442 throw new SAMLRequesterException( 2443 SAMLUtils.bundle.getString("nullInput")); 2444 } 2445 2446 Map partner = (Map) SAMLServiceManager.getAttribute( 2447 SAMLConstants.PARTNER_URLS); 2448 if ((partner == null) || (!partner.containsKey(destID))) { 2449 SAMLUtils.debug.error("AssertionManager.createAssertionArtifact:" + 2450 "(String, String): destID not in partner list."); 2451 throw new SAMLException( 2452 SAMLUtils.bundle.getString("destIDNotFound")); 2453 } 2454 2455 // create assertion id and artifact 2456 String handle = SAMLUtils.generateAssertionHandle(); 2457 if (handle == null) { 2458 if (SAMLUtils.debug.messageEnabled()) { 2459 SAMLUtils.debug.message("AssertionManager.createAssertionArt" 2460 + "ifact: couldn't generate assertion handle."); 2461 } 2462 throw new SAMLResponderException( 2463 SAMLUtils.bundle.getString("errorCreateArtifact")); 2464 } 2465 2466 String sourceID = (String) SAMLServiceManager.getAttribute( 2467 SAMLConstants.SITE_ID); 2468 AssertionArtifact art = new AssertionArtifact(sourceID, handle); 2469 Assertion assertion = createSSOAssertion(id, art, 2470 request, response, destID, targetUrl, version); 2471 try { 2472 if (version != null) { 2473 StringTokenizer st = new StringTokenizer(version,"."); 2474 if (st.countTokens() == 2) { 2475 assertion.setMajorVersion( 2476 Integer.parseInt(st.nextToken().trim())); 2477 assertion.setMinorVersion( 2478 Integer.parseInt(st.nextToken().trim())); 2479 } 2480 } 2481 } catch (NumberFormatException ne) { 2482 throw new SAMLException(ne.getMessage()); 2483 } 2484 return art; 2485 } 2486 2487 /** 2488 * This method returns the decision of an AuthorizationQuery. 2489 * @param authZQuery An AuthorizationQuery that contains the question: 2490 * Is this subject authorized to perfrom this action on 2491 * this resource? 2492 * @param destID the SourceID of the site where the query is from. 2493 * @return an int whose value is defined in 2494 * AuthorizationDecisionStatement.DecisionType. 2495 */ 2496 public int isAllowed(AuthorizationDecisionQuery authZQuery, String destID) { 2497 if (authZQuery == null) { 2498 SAMLUtils.debug.error("AssertionManager.isAllowed: null input."); 2499 return AuthorizationDecisionStatement.DecisionType.INDETERMINATE; 2500 } 2501 2502 Assertion assertion = null; 2503 try { 2504 assertion = getAuthorizationDecisionAssertion(authZQuery, destID, 2505 false); 2506 } catch (SAMLException e) { 2507 SAMLUtils.debug.error("AssertionManager.isAllowed: exception thrown" 2508 + " when trying to get an assertion from authZQuery. ", e); 2509 return AuthorizationDecisionStatement.DecisionType.INDETERMINATE; 2510 } 2511 2512 // double check, shouldn't be here 2513 if (assertion == null) { 2514 return AuthorizationDecisionStatement.DecisionType.INDETERMINATE; 2515 } 2516 2517 // Got an assertion 2518 Set statements = assertion.getStatement(); 2519 if ((statements != null) && (!statements.isEmpty())) { 2520 Iterator iter = statements.iterator(); 2521 while (iter.hasNext()) { 2522 Statement statement = (Statement) iter.next(); 2523 if (statement.getStatementType() == 2524 Statement.AUTHORIZATION_DECISION_STATEMENT) 2525 { 2526 // we know there should be only one authZstatement 2527 return ((AuthorizationDecisionStatement) statement). 2528 getDecision(); 2529 } 2530 } 2531 // still here means no authZstatement 2532 SAMLUtils.debug.error("AssertionManager.isAllowed: no " 2533 + "authZstatement in assertion."); 2534 return AuthorizationDecisionStatement.DecisionType.INDETERMINATE; 2535 } else { 2536 SAMLUtils.debug.error("AssertionManager.isAllowed: no statements in" 2537 + " assertion."); 2538 return AuthorizationDecisionStatement.DecisionType.INDETERMINATE; 2539 } 2540 } 2541 2542 boolean validateNumberOfAssertions(Map idEntryMap) 2543 throws SAMLResponderException 2544 { 2545 Integer maxNumber = (Integer) SAMLServiceManager.getAttribute( 2546 SAMLConstants.ASSERTION_MAX_NUMBER_NAME); 2547 int maxValue = maxNumber.intValue(); 2548 if ((maxValue != 0) && (idEntryMap.size() > maxValue)) { 2549 SAMLUtils.debug.error("AssertionManager.createAssertion" 2550 + "Artifact(assertion,String): reached maxNumber of " 2551 + "assertions."); 2552 throw new SAMLResponderException( 2553 SAMLUtils.bundle.getString("errorCreateArtifact")); 2554 } else { 2555 return false; 2556 } 2557 } 2558 2559 private class GoThroughRunnable extends GeneralTaskRunnable { 2560 private Set keys; 2561 private long runPeriod; 2562 2563 public GoThroughRunnable(long runPeriod) { 2564 this.keys = new HashSet(); 2565 this.runPeriod = runPeriod; 2566 } 2567 2568 public boolean addElement(Object obj) { 2569 synchronized (keys) { 2570 return keys.add(obj); 2571 } 2572 } 2573 2574 public boolean removeElement(Object obj) { 2575 synchronized (keys) { 2576 return keys.remove(obj); 2577 } 2578 } 2579 2580 public boolean isEmpty() { 2581 return false; 2582 } 2583 2584 public long getRunPeriod() { 2585 return runPeriod; 2586 } 2587 2588 public void run() { 2589 long currentTime = currentTimeMillis(); 2590 String keyString; 2591 Entry entry; 2592 Assertion assertion; 2593 SAMLUtils.debug.message("Clean up runnable wakes up.."); 2594 synchronized (keys) { 2595 Iterator keyIter = keys.iterator(); 2596 if (SAMLUtils.debug.messageEnabled()) { 2597 SAMLUtils.debug.message("AssertionManager::" 2598 +"CleanUpThread::number of assertions in " 2599 + "IdEntryMap:"+idEntryMap.size()); 2600 } 2601 while (keyIter.hasNext()) { 2602 keyString = (String) keyIter.next(); 2603 entry = (Entry) idEntryMap.get(keyString); 2604 if (entry != null) { 2605 assertion = entry.getAssertion(); 2606 if (assertion != null) { 2607 if (assertion.getConditions() != null) { 2608 if (!assertion.isTimeValid()) { 2609 keyIter.remove(); 2610 deleteAssertion(keyString, null); 2611 } 2612 } else { 2613 // if conditions are absent, calculate time 2614 // validity of assertion as if notBefore is 2615 // issueInstant - notBeforeSkew and notOnOrAfter 2616 // is assertion time out + issueInstant 2617 2618 Date issueInstant = assertion.getIssueInstant(); 2619 Date notBefore = new Date(issueInstant.getTime() 2620 - notBeforeSkew); 2621 Date notOnOrAfter = new Date( 2622 issueInstant.getTime() + assertionTimeout); 2623 if (!((currentTime >= notBefore.getTime()) && 2624 (currentTime < notOnOrAfter.getTime()))) { 2625 keyIter.remove(); 2626 deleteAssertion(keyString, null); 2627 } 2628 } 2629 } 2630 } 2631 } 2632 } 2633 } 2634 } 2635 2636}