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 */ 028/** 029 * Portions Copyrighted 2013 ForgeRock AS 030 */ 031package com.sun.identity.saml; 032 033import java.util.Map; 034import java.util.HashMap; 035import java.util.Date; 036import java.util.List; 037import java.util.ArrayList; 038import java.util.Set; 039import java.util.HashSet; 040import java.util.Iterator; 041import java.net.InetAddress; 042import org.w3c.dom.Element; 043import com.sun.identity.common.GeneralTaskRunnable; 044import com.sun.identity.common.PeriodicGroupRunnable; 045import com.sun.identity.common.ScheduleableGroupAction; 046import com.sun.identity.common.SystemTimerPool; 047import com.sun.identity.common.TaskRunnable; 048import com.sun.identity.common.TimerPool; 049import com.sun.identity.saml.assertion.*; 050import com.sun.identity.saml.protocol.*; 051import com.sun.identity.saml.common.*; 052import com.sun.identity.saml.plugins.*; 053import com.sun.identity.saml.xmlsig.*; 054import com.sun.identity.shared.Constants; 055import com.sun.identity.shared.DateUtils; 056import com.sun.identity.common.SystemConfigurationUtil; 057import com.sun.identity.shared.encode.Base64; 058import com.sun.identity.shared.stats.Stats; 059import com.sun.identity.shared.xml.XMLUtils; 060import java.util.StringTokenizer; 061import com.sun.identity.plugin.monitoring.FedMonAgent; 062import com.sun.identity.plugin.monitoring.FedMonSAML1Svc; 063import com.sun.identity.plugin.monitoring.MonitorManager; 064import com.sun.identity.plugin.session.SessionException; 065import com.sun.identity.plugin.session.SessionManager; 066import com.sun.identity.plugin.session.SessionProvider; 067import javax.servlet.http.HttpServletRequest; 068import javax.servlet.http.HttpServletResponse; 069 070/** 071 * The class <code>AssertionManager</code> is a <code>final</code> class 072 * that provides interfaces to create, get and destroy <code>Assertion</code>s. 073 * <p> 074 * It is a singleton class; an instance of this class can be obtained by 075 * calling <code>AssertionManager.getInstance()</code>. 076 * <p> 077 * Having obtained an instance of <code>AssertionManager</code>, its methods 078 * can be called to create/get <code>Assertion</code>, and 079 * <code>AssertionArtifact</code>, and to obtain decision from an 080 * <code>Query</code>. 081 * <p> 082 * This class could only be used in the same JVM as the OpenSSO. 083 * @supported.api 084 */ 085public final class AssertionManager { 086 087 // General stats class 088 public static Stats assStats; 089 public static Stats artStats; 090 091 // Assertion Statistics Class 092 private static AssertionStats assertionStats; 093 094 // Artifact Statistics Class 095 private static ArtifactStats artifactStats; 096 097 private static final String SUPER_USER = 098 "com.sun.identity.authentication.super.user"; 099 private static String superUser = null; 100 private static SessionProvider sessionProvider = null; 101 102 private static long cleanUpInterval; 103 private static long assertionTimeout; 104 private static long artifactTimeout; 105 private static long notBeforeSkew; 106 107 private static FedMonAgent agent; 108 private static FedMonSAML1Svc saml1Svc; 109 110 static { 111 assStats = Stats.getInstance("amAssertionMap"); 112 artStats = Stats.getInstance("amArtifactMap"); 113 superUser = SystemConfigurationUtil.getProperty(SUPER_USER); 114 try { 115 sessionProvider = SessionManager.getProvider(); 116 } catch (SessionException se) { 117 SAMLUtils.debug.error("Static: Couldn't get SessionProvider.", 118 se); 119 sessionProvider = null; 120 } 121 cleanUpInterval = ((Integer) SAMLServiceManager.getAttribute( 122 SAMLConstants.CLEANUP_INTERVAL_NAME)).intValue() * 1000; 123 artifactTimeout = ((Integer) SAMLServiceManager.getAttribute( 124 SAMLConstants.ARTIFACT_TIMEOUT_NAME)).intValue() * 1000; 125 assertionTimeout = ((Integer) SAMLServiceManager.getAttribute( 126 SAMLConstants.ASSERTION_TIMEOUT_NAME)).intValue() * 1000; 127 notBeforeSkew = ((Integer) SAMLServiceManager.getAttribute( 128 SAMLConstants.NOTBEFORE_TIMESKEW_NAME)).intValue() * 1000; 129 130 agent = MonitorManager.getAgent(); 131 saml1Svc = MonitorManager.getSAML1Svc(); 132 } 133 134 // Singleton instance of AssertionManager 135 private static AssertionManager instance = null; 136 137 // used to store artifact to assertionID mapping 138 private static Map artEntryMap = null; 139 // used to store assertionIDString to entry mapping 140 private static Map idEntryMap = null; 141 142 private static TaskRunnable assertionTimeoutRunnable; 143 private static TaskRunnable artifactTimeoutRunnable; 144 private static TaskRunnable goThroughRunnable; 145 146 private static String assertionVersion = null; 147 private static String protocolVersion = null; 148 149 150 private class Entry { 151 private String destID = null; 152 private String artString = null; 153 private Object token = null; 154 private Assertion assertion = null; 155 156 public Entry(Assertion assertion, String destID, String artString, 157 Object token) 158 { 159 this.assertion = assertion; 160 this.destID = destID; 161 this.artString = artString; 162 this.token = token; 163 } 164 165 public Assertion getAssertion() { 166 return assertion; 167 } 168 169 public String getDestID() { 170 return destID; 171 } 172 173 public void setDestID(String newDestID) { 174 destID = newDestID; 175 } 176 177 public String getArtifactString() { 178 return artString; 179 } 180 181 public void setArtifactString(String newArtifactString) { 182 artString = newArtifactString; 183 } 184 185 public Object getSSOToken() { 186 return token; 187 } 188 } 189 190 private class ArtEntry { 191 private String aID = null; 192 private long expiretime = 0; 193 194 public ArtEntry(String aID, long expiretime) { 195 this.aID = aID; 196 this.expiretime = expiretime; 197 } 198 199 public String getAssertionID() { 200 return aID; 201 } 202 203 public long getExpireTime() { 204 return expiretime; 205 } 206 } 207 208 /** 209 * Default Constructor 210 */ 211 private AssertionManager() { 212 idEntryMap = new HashMap(); 213 artEntryMap = new HashMap(); 214 try { 215 assertionVersion = SystemConfigurationUtil.getProperty( 216 SAMLConstants.SAML_ASSERTION_VERSION); 217 protocolVersion = SystemConfigurationUtil.getProperty( 218 SAMLConstants.SAML_PROTOCOL_VERSION); 219 } catch (Exception e) { 220 assertionVersion = SAMLConstants.ASSERTION_VERSION_1_0; 221 protocolVersion = SAMLConstants.PROTOCOL_VERSION_1_0; 222 } 223 TimerPool timerPool = SystemTimerPool.getTimerPool(); 224 ScheduleableGroupAction assertionTimeoutAction = new 225 ScheduleableGroupAction() { 226 public void doGroupAction(Object obj) { 227 deleteAssertion((String) obj, null); 228 } 229 }; 230 231 assertionTimeoutRunnable = new PeriodicGroupRunnable( 232 assertionTimeoutAction, cleanUpInterval, assertionTimeout, true); 233 timerPool.schedule(assertionTimeoutRunnable, new Date((( 234 System.currentTimeMillis() + cleanUpInterval) / 1000) * 1000)); 235 236 ScheduleableGroupAction artifactTimeoutAction = new 237 ScheduleableGroupAction() { 238 public void doGroupAction(Object obj) { 239 deleteAssertion(null, (String) obj); 240 } 241 }; 242 243 artifactTimeoutRunnable = new PeriodicGroupRunnable( 244 artifactTimeoutAction, cleanUpInterval, artifactTimeout, true); 245 246 timerPool.schedule(artifactTimeoutRunnable, new Date((( 247 System.currentTimeMillis() + cleanUpInterval) / 1000) * 1000)); 248 249 goThroughRunnable = new GoThroughRunnable(cleanUpInterval); 250 251 timerPool.schedule(goThroughRunnable, new Date((( 252 System.currentTimeMillis() + cleanUpInterval) / 1000) * 1000)); 253 254 if (assStats.isEnabled()) { 255 artifactStats = new ArtifactStats(artEntryMap); 256 artStats.addStatsListener(artifactStats); 257 assertionStats = new AssertionStats(idEntryMap); 258 assStats.addStatsListener(assertionStats); 259 } 260 261 } 262 263 /** 264 * Gets the singleton instance of <code>AssertionManager</code>. 265 * @return The singleton <code>AssertionManager</code> instance 266 * @throws SAMLException if unable to get the singleton 267 * <code>AssertionManager</code> instance. 268 * @supported.api 269 */ 270 public static AssertionManager getInstance() throws SAMLException { 271 // not throwing any exception 272 if (instance == null) { 273 synchronized (AssertionManager.class) { 274 if (instance == null) { 275 if (SAMLUtils.debug.messageEnabled() ) { 276 SAMLUtils.debug.message("Constructing a new instance" 277 + " of AssertionManager"); 278 } 279 instance = new AssertionManager(); 280 } 281 } 282 } 283 return instance; 284 } 285 286 /** 287 * This method creates an Assertion that contains an 288 * <code>AuthenticationStatement</code>. 289 * @param token user's session object that contains authentication 290 * information which is needed to create the 291 * <code>AuthenticationStatement</code>. 292 * @return Assertion The created Assertion. 293 * @throws SAMLException If the Assertion cannot be created. 294 * @supported.api 295 */ 296 public Assertion createAssertion(Object token) 297 throws SAMLException 298 { 299 if (assertionVersion.equals(SAMLConstants.ASSERTION_VERSION_1_0)) { 300 return createAssertion(token, null, 301 SAMLConstants.DEPRECATED_CONFIRMATION_METHOD_ARTIFACT, 0); 302 } else if(assertionVersion.equals( 303 SAMLConstants.ASSERTION_VERSION_1_1)) { 304 return createAssertion(token, null, 305 SAMLConstants.CONFIRMATION_METHOD_ARTIFACT, 1); 306 } else { 307 throw new SAMLException(SAMLUtils.bundle.getString( 308 "assertionVersionNotSupport")); 309 } 310 } 311 312 /** 313 * This method creates an Assertion that contains an 314 * <code>AuthenticationStatement</code> and 315 * an <code>AttributeStatement</code>. 316 * @param token User' session object that contains authentication 317 * information which is needed to create the 318 * <code>AuthenticationStatement</code> for the Assertion. 319 * @param attributes A list of Attribute objects which are used to 320 * create the <code>AttributeStatement</code> for the Assertion. 321 * @return Assertion The created Assertion. 322 * @throws SAMLException If the Assertion cannot be created. 323 * @supported.api 324 */ 325 public Assertion createAssertion(Object token, List attributes) 326 throws SAMLException 327 { if (assertionVersion.equals(SAMLConstants.ASSERTION_VERSION_1_0)) { 328 return createAssertion(token, attributes, 329 SAMLConstants.DEPRECATED_CONFIRMATION_METHOD_ARTIFACT, 0); 330 } else if (assertionVersion.equals( 331 SAMLConstants.ASSERTION_VERSION_1_1)) { 332 return createAssertion(token, attributes, 333 SAMLConstants.CONFIRMATION_METHOD_ARTIFACT, 1); 334 } else { 335 throw new SAMLException(SAMLUtils.bundle.getString( 336 "assertionVersionNotSupport")); 337 } 338 } 339 340 private Assertion createAssertion(Object token, List attributes, 341 String confirmationMethod, int minorVersion) 342 throws SAMLException 343 { 344 if (token == null) { 345 SAMLUtils.debug.error("AssertionManager.createAssertion(id):" 346 + "input Session is null."); 347 throw new SAMLException(SAMLUtils.bundle.getString("nullInput")); 348 } 349 if (sessionProvider == null) { 350 throw new SAMLException(SAMLUtils.bundle.getString( 351 "nullSessionProvider")); 352 } 353 String id = sessionProvider.getSessionID(token); 354 return createAssertion(id, null, null, attributes, 355 confirmationMethod, minorVersion, null); 356 } 357 358 /** 359 * This method creates an <code>AssertionArtifact</code> for the given 360 * Assertion. 361 * 362 * @param assertion The Assertion for which an Artifact needs to be created. 363 * @param destID The <code>sourceID</code> of the site for which the 364 * <code>AssertionArtifact</code> is created. It is in raw String 365 * format (not Base64 encoded, for example.) This String can be 366 * obtained from converting the 20 bytes sequence to char Array, then 367 * from the char Array to String. 368 * @return <code>AssertionArtifact</code> 369 * @throws SAMLException If the <code>AssertionArtifact</code> cannot be 370 * created. 371 * @supported.api 372 */ 373 public AssertionArtifact createAssertionArtifact(Assertion assertion, 374 String destID) 375 throws SAMLException 376 { 377 if ((assertion == null) || (destID == null) || (destID.length() == 0)) { 378 SAMLUtils.debug.error("AssertionManager.createAssertionArti" 379 + "fact(Assertion, String): null input."); 380 throw new SAMLException(SAMLUtils.bundle.getString("nullInput")); 381 } 382 383 Map partner = (Map) SAMLServiceManager.getAttribute( 384 SAMLConstants.PARTNER_URLS); 385 if ((partner == null) || (!partner.containsKey(destID))) { 386 SAMLUtils.debug.error("AssertionManager.createAssertionArtifact:" + 387 "(Assertion, String): destID not in partner list."); 388 throw new SAMLException( 389 SAMLUtils.bundle.getString("destIDNotFound")); 390 } 391 392 String handle = SAMLUtils.generateAssertionHandle(); 393 if (handle == null) { 394 SAMLUtils.debug.error("AssertionManager.createAssertion" 395 + "Artifact(Assertion,String): couldn't generate " 396 + "assertion handle."); 397 throw new SAMLResponderException( 398 SAMLUtils.bundle.getString("errorCreateArtifact")); 399 } 400 String sourceID = (String) SAMLServiceManager.getAttribute( 401 SAMLConstants.SITE_ID); 402 AssertionArtifact art = new AssertionArtifact(sourceID, handle); 403 String artString = art.getAssertionArtifact(); 404 String aID = assertion.getAssertionID(); 405 Entry entry = (Entry) idEntryMap.get(aID); 406 if ((agent != null) && agent.isRunning() && (saml1Svc != null)) { 407 saml1Svc.incSAML1Cache(FedMonSAML1Svc.ASSERTIONS, 408 FedMonSAML1Svc.CREAD); 409 } 410 if ((entry == null) && !validateNumberOfAssertions(idEntryMap)) { 411 if ((agent != null) && agent.isRunning() && (saml1Svc != null)) { 412 saml1Svc.incSAML1Cache(FedMonSAML1Svc.ASSERTIONS, 413 FedMonSAML1Svc.CMISS); 414 } 415 entry = new Entry(assertion, destID, artString, null); 416 try { 417 synchronized (idEntryMap) { 418 idEntryMap.put(aID, entry); 419 } 420 if ((agent != null) && 421 agent.isRunning() && 422 (saml1Svc != null)) 423 { 424 saml1Svc.incSAML1Cache( 425 FedMonSAML1Svc.ASSERTIONS, 426 FedMonSAML1Svc.CWRITE); 427 } 428 goThroughRunnable.addElement(aID); 429 } catch (Exception e) { 430 SAMLUtils.debug.error("AssertionManager.createAssertion" 431 + "Artifact(Assertion,String): couldn't add to " 432 + "idEntryMap." + e); 433 throw new SAMLResponderException( 434 SAMLUtils.bundle.getString("errorCreateArtifact")); 435 } 436 if (LogUtils.isAccessLoggable(java.util.logging.Level.FINER)) { 437 String[] data = {SAMLUtils.bundle.getString("assertionCreated"), 438 assertion.toString(true, true)}; 439 LogUtils.access(java.util.logging.Level.FINER, 440 LogUtils.ASSERTION_CREATED, data); 441 } else { 442 String[] data = {SAMLUtils.bundle.getString("assertionCreated"), 443 assertion.getAssertionID()}; 444 LogUtils.access(java.util.logging.Level.INFO, 445 LogUtils.ASSERTION_CREATED, data); 446 } 447 } else { 448 if ((agent != null) && agent.isRunning() && (saml1Svc != null)) { 449 saml1Svc.incSAML1Cache(FedMonSAML1Svc.ASSERTIONS, 450 FedMonSAML1Svc.CHIT); 451 } 452 String preArtString = entry.getArtifactString(); 453 if (preArtString != null) { 454 if ((agent != null) && 455 agent.isRunning() && 456 (saml1Svc != null)) 457 { 458 saml1Svc.incSAML1Cache( 459 FedMonSAML1Svc.ARTIFACTS, 460 FedMonSAML1Svc.CREAD); 461 } 462 463 if (artEntryMap.containsKey(preArtString)) { 464 if ((agent != null) && 465 agent.isRunning() && 466 (saml1Svc != null)) 467 { 468 saml1Svc.incSAML1Cache( 469 FedMonSAML1Svc.ARTIFACTS, 470 FedMonSAML1Svc.CHIT); 471 } 472 SAMLUtils.debug.error("AssertionManager.createAssertion" 473 + "Artifact(Asssertion, String): Artifact exists for " 474 + "the assertion."); 475 throw new SAMLResponderException( 476 SAMLUtils.bundle.getString("errorCreateArtifact")); 477 } else { 478 if ((agent != null) && 479 agent.isRunning() && 480 (saml1Svc != null)) 481 { 482 saml1Svc.incSAML1Cache( 483 FedMonSAML1Svc.ARTIFACTS, 484 FedMonSAML1Svc.CMISS); 485 } 486 } 487 } 488 entry.setDestID(destID); 489 entry.setArtifactString(artString); 490 } 491 // add to artEntry map 492 try { 493 Object oldEntry = null; 494 synchronized (artEntryMap) { 495 oldEntry = artEntryMap.put(artString, new 496 ArtEntry(aID, System.currentTimeMillis() + 497 artifactTimeout)); 498 } 499 if (oldEntry != null) { 500 artifactTimeoutRunnable.removeElement(artString); 501 } 502 artifactTimeoutRunnable.addElement(artString); 503 if ((agent != null) && agent.isRunning() && (saml1Svc != null)) { 504 saml1Svc.incSAML1Cache(FedMonSAML1Svc.ARTIFACTS, 505 FedMonSAML1Svc.CWRITE); 506 } 507 } catch (Exception e) { 508 SAMLUtils.debug.error("AssertionManager.createAssertionArt" 509 + "fact(Assertion,String): couldn't add artifact to the " 510 + "artEntryMap", e); 511 throw new SAMLResponderException( 512 SAMLUtils.bundle.getString("errorCreateArtifact")); 513 } 514 String[] data = {SAMLUtils.bundle.getString("assertionArtifactCreated"), 515 artString, aID}; 516 LogUtils.access(java.util.logging.Level.INFO, 517 LogUtils.ASSERTION_ARTIFACT_CREATED, data); 518 return art; 519 } 520 521 /** 522 * This method gets all valid Assertions managed by this 523 * <code>AssertionManager</code>. 524 * @param token User's session object which is allowed to get all 525 * Assertion. 526 * @return A Set of valid Assertion IDs. Each element in the Set is a 527 * String representing an Assertion ID. 528 * @throws SAMLException If this method can not gets all valid Assertions. 529 * @supported.api 530 */ 531 public Set getAssertions(Object token) 532 throws SAMLException 533 { 534 if (token == null) { 535 SAMLUtils.debug.error("AssertionManager.getAssertions(Object" 536 + "): input session is null."); 537 throw new SAMLException(SAMLUtils.bundle.getString("nullInput")); 538 } 539 540 if (!isSuperUser(token)) { 541 SAMLUtils.debug.error("AssertionManager.getAssertions(Object" 542 + "): Session doesn't have the privilege."); 543 throw new SAMLException(SAMLUtils.bundle.getString("noPrivilege")); 544 } 545 546 return idEntryMap.keySet(); 547 } 548 549 private boolean isSuperUser(Object token) { 550 try { 551 if (sessionProvider == null) { 552 SAMLUtils.debug.error("SessionProvider is null."); 553 return false; 554 } 555 String userID = (String) sessionProvider.getProperty(token, 556 Constants.UNIVERSAL_IDENTIFIER)[0]; 557 if (superUser != null && superUser.length() > 0) { 558 return superUser.equalsIgnoreCase(userID); 559 } 560 } catch (Exception e) { 561 if (SAMLUtils.debug.messageEnabled()) { 562 SAMLUtils.debug.message( 563 "AssertionManager.isSuperUser:Exception: ", e); 564 } 565 } 566 return false; 567 } 568 569 /** 570 * This method gets the Assertion based on the Assertion ID. 571 * @param id The Assertion ID. 572 * @return An Assertion identified by the Assertion ID. 573 * @throws SAMLException If this method can not get the Assertion. 574 */ 575 public Assertion getAssertion(String id) 576 throws SAMLException 577 { 578 if ((id == null) || (id.length() == 0)) { 579 SAMLUtils.debug.error("AssertionManager.getAssetion(String): " 580 + "id is null."); 581 throw new SAMLException(SAMLUtils.bundle.getString("nullInput")); 582 } 583 AssertionIDReference idRef = new AssertionIDReference(id); 584 return getAssertion(idRef, null, false); 585 } 586 587 /** 588 * This method gets all valid <code>AssertionArtifacts</code> 589 * managed by this <code>AssertionManager</code>. 590 * 591 * @param token User's session object which is allowed to get all 592 * <code>AssertionArtifacts</code>. 593 * @return A Set of valid <code>AssertionArtifacts</code>. Each element in 594 * the Set is an <code>AssertionArtifacts</code> object representing 595 * an artifact. 596 * @throws SAMLException If this method can not gets all valid 597 * <code>AssertionArtifacts</code>. 598 * @supported.api 599 */ 600 public Set getAssertionArtifacts(Object token) 601 throws SAMLException 602 { 603 if (token == null) { 604 SAMLUtils.debug.error("AssertionManager.getAssertionArtifacts(" + 605 "Object token): input token is null."); 606 throw new SAMLException(SAMLUtils.bundle.getString("nullInput")); 607 } 608 609 if (!isSuperUser(token)) { 610 SAMLUtils.debug.error("AssertionManager.getAssertionArtifacts(" + 611 "Object token): Session doesn't have the privilege."); 612 throw new SAMLException(SAMLUtils.bundle.getString("noPrivilege")); 613 } 614 615 return artEntryMap.keySet(); 616 } 617 618 /** 619 * Returns Assertion that contains <code>AuthenticationStatement</code>. 620 * @param id The String that contains authentication information which 621 * is needed to create the assertion. It could be a string 622 * representation of an id, a cookie, etc. 623 * @param artifact the value to be set in the SubjectConfirmation of the 624 * <code>AuthenticationStatement</code>. If it's null, 625 * <code>SubjectConfirmation</code> is set to bearer. 626 * @param destID A String that is the site the assertion is created for. 627 * @param targetUrl A URL String representing the target site 628 * @param version The relying party preferred Assertion version number. 629 * @return Assertion The created Assertion. 630 * @throws SAMLException If the Assertion cannot be created. 631 */ 632 public Assertion createSSOAssertion(String id, AssertionArtifact artifact, 633 String destID, String targetUrl, String version) 634 throws SAMLException { 635 return createSSOAssertion(id, artifact, null, null, destID, 636 targetUrl, version); 637 } 638 639 /** 640 * Returns Assertion that contains <code>AuthenticationStatement</code>. 641 * @param id The String that contains authentication information which 642 * is needed to create the assertion. It could be a string 643 * representation of an id, a cookie, etc. 644 * @param artifact the value to be set in the SubjectConfirmation of the 645 * <code>AuthenticationStatement</code>. If it's null, 646 * <code>SubjectConfirmation</code> is set to bearer. 647 * @param request The HttpServletRerquest object of the request. 648 * @param response The HttpServletResponse object. 649 * @param destID A String that is the site the assertion is created for. 650 * @param targetUrl A URL String representing the target site 651 * @param version The relying party preferred Assertion version number. 652 * @return Assertion The created Assertion. 653 * @throws SAMLException If the Assertion cannot be created. 654 */ 655 public Assertion createSSOAssertion(String id, AssertionArtifact artifact, 656 HttpServletRequest request, HttpServletResponse response, 657 String destID, String targetUrl, String version) 658 throws SAMLException 659 { 660 List attributes = null; 661 Map partnerURLs = (Map) SAMLServiceManager.getAttribute( 662 SAMLConstants.PARTNER_URLS); 663 SAMLServiceManager.SOAPEntry partnerEntry = 664 (SAMLServiceManager.SOAPEntry)partnerURLs.get(destID); 665 666 if (partnerEntry != null) { 667 try { 668 if (sessionProvider == null) { 669 throw new SAMLException(SAMLUtils.bundle.getString( 670 "nullSessionProvider")); 671 } 672 Object userSession = sessionProvider.getSession(id); 673 ConsumerSiteAttributeMapper cMapper = 674 partnerEntry.getConsumerSiteAttributeMapper(); 675 if (cMapper != null) { 676 attributes = cMapper.getAttributes(userSession, 677 request, response, targetUrl); 678 } else { 679 PartnerSiteAttributeMapper pMapper = 680 partnerEntry.getPartnerSiteAttributeMapper(); 681 if (pMapper != null) { 682 attributes = pMapper.getAttributes( 683 userSession, targetUrl); 684 } else { 685 SiteAttributeMapper mapper = 686 partnerEntry.getSiteAttributeMapper(); 687 if (mapper != null) { 688 attributes = mapper.getAttributes(userSession); 689 } 690 } 691 } 692 } catch ( SessionException ssoe) { 693 SAMLUtils.debug.error("AssertionManager.createAssertion(id):" 694 + " exception retrieving info from the Session", ssoe); 695 return null; 696 } 697 } 698 699 String nameIDFormat = request.getParameter( 700 SAMLConstants.NAME_ID_FORMAT); 701 if (artifact == null) { 702 // SAML post profile 703 if (version.equals(SAMLConstants.ASSERTION_VERSION_1_1)) { 704 // set minor version to 1 705 return createAssertion(id, artifact, destID, attributes, 706 SAMLConstants.CONFIRMATION_METHOD_BEARER, 1, nameIDFormat); 707 } else { 708 // set minor version to 0 709 return createAssertion(id, artifact, destID, attributes, 710 SAMLConstants.CONFIRMATION_METHOD_BEARER, 0, nameIDFormat); 711 } 712 } else { 713 if(version == null || version.equals( 714 SAMLConstants.ASSERTION_VERSION_1_0)) { 715 return createAssertion(id, artifact, destID, attributes, 716 SAMLConstants.DEPRECATED_CONFIRMATION_METHOD_ARTIFACT, 0, 717 nameIDFormat); 718 } else if (version.equals(SAMLConstants.ASSERTION_VERSION_1_1)) { 719 return createAssertion(id, artifact, destID, attributes, 720 SAMLConstants.CONFIRMATION_METHOD_ARTIFACT, 1, 721 nameIDFormat); 722 } else { 723 SAMLUtils.debug.error("Input version " + version + 724 " is not supported."); 725 return null; 726 } 727 } 728 } 729 730 private Assertion createAssertion(String id, AssertionArtifact artifact, 731 String destID, List attributes, String confirmationMethod, 732 int minorVersion, String nameIDFormat) throws SAMLException 733 { 734 // check input 735 if ((id == null) || (id.length() == 0)) { 736 if (SAMLUtils.debug.messageEnabled()) { 737 SAMLUtils.debug.message("AssertionManager.createAssertion(id):" 738 + "null input."); 739 } 740 throw new SAMLException(SAMLUtils.bundle.getString("nullInput")); 741 } 742 validateNumberOfAssertions(idEntryMap); 743 String authMethod = null; 744 Date authInstant = null; 745 Object token = null; 746 String clientIP = null; 747 try { 748 if (sessionProvider == null) { 749 throw new SAMLException(SAMLUtils.bundle.getString( 750 "nullSessionProvider")); 751 } 752 token = sessionProvider.getSession(id); 753 authMethod = (String) sessionProvider.getProperty( 754 token, SessionProvider.AUTH_METHOD)[0]; 755 String authSSOInstant = (String) 756 sessionProvider.getProperty(token,"authInstant")[0]; 757 if (authSSOInstant == null || authSSOInstant.equals("")) { 758 authInstant = new Date(); 759 } else { 760 authInstant = DateUtils.stringToDate(authSSOInstant); 761 } 762 763 try { 764 InetAddress clientIPAddress = 765 InetAddress.getByName(sessionProvider.getProperty( 766 token,"Host")[0]); 767 clientIP = clientIPAddress.getHostAddress(); 768 } catch (Exception e) { 769 // catching exception here since client ip is optional 770 if (SAMLUtils.debug.messageEnabled()) { 771 SAMLUtils.debug.message("AssertionManager." + 772 "createAssertion(id):" + 773 "exception when obtaining client ip: ", e); 774 } 775 } 776 } catch (Exception e) { 777 SAMLUtils.debug.error("AssertionManager." + 778 "createAssertion(id):" + 779 " exception retrieving info from the Session: ", e); 780 return null; 781 } 782 783 Map partnerURLs = 784 (Map) SAMLServiceManager.getAttribute(SAMLConstants.PARTNER_URLS); 785 SAMLServiceManager.SOAPEntry partnerEntry = 786 (SAMLServiceManager.SOAPEntry)partnerURLs.get(destID); 787 788 NameIdentifierMapper niMapper = null; 789 if (partnerEntry != null) { 790 niMapper = partnerEntry.getNameIdentifierMapper(); 791 } 792 if (niMapper == null) { 793 niMapper = new DefaultNameIdentifierMapper(); 794 } 795 796 String srcID = 797 (String)SAMLServiceManager.getAttribute(SAMLConstants.SITE_ID); 798 799 NameIdentifier ni = niMapper.getNameIdentifier(token, srcID, destID, nameIDFormat); 800 if (ni == null) { 801 SAMLUtils.debug.error("AssertionManager.createAssertion(id): " + 802 "name identifier is null."); 803 return null; 804 } 805 806 SubjectConfirmation subConfirmation = null; 807 String artString = null; 808 if ((confirmationMethod != null) && (confirmationMethod.length() > 0)) { 809 subConfirmation = new SubjectConfirmation(confirmationMethod); 810 } else { 811 if (artifact != null) { 812 if (minorVersion == 0) { 813 // set default for SAML Artifact profile 814 // here, we use SAML 1.0 confirmation method as default. 815 confirmationMethod = 816 SAMLConstants.DEPRECATED_CONFIRMATION_METHOD_ARTIFACT; 817 } else { 818 confirmationMethod = 819 SAMLConstants.CONFIRMATION_METHOD_ARTIFACT; 820 } 821 subConfirmation = new SubjectConfirmation(confirmationMethod); 822 } else { 823 // set to bearer for POST profile 824 subConfirmation = new SubjectConfirmation( 825 SAMLConstants.CONFIRMATION_METHOD_BEARER); 826 } 827 } 828 829 if (artifact != null) { 830 artString = artifact.getAssertionArtifact(); 831 } 832 Subject sub = new Subject(ni, subConfirmation); 833 SubjectLocality subjLocality = null; 834 if ((clientIP != null) && (clientIP.length() != 0)) { 835 subjLocality = new SubjectLocality(clientIP, null); 836 } 837 Set statements = new HashSet(); 838 statements.add(new AuthenticationStatement(authMethod, authInstant, 839 sub, subjLocality, null)); 840 841 if ((attributes != null) && (!attributes.isEmpty())) { 842 statements.add(new AttributeStatement(sub, attributes)); 843 } 844 Date issueInstant = new Date(); 845 Date notBefore = new Date(issueInstant.getTime() - notBeforeSkew); 846 // TODO: this period will be different for bearer 847 Date notAfter = new Date(issueInstant.getTime() + assertionTimeout); 848 Conditions cond = new Conditions(notBefore, notAfter); 849 String issuer = (String) SAMLServiceManager.getAttribute( 850 SAMLConstants.ISSUER_NAME); 851 Assertion assertion = new Assertion(null, issuer, issueInstant, cond, 852 statements); 853 assertion.setMinorVersion(minorVersion); 854 String aIDString = assertion.getAssertionID(); 855 856 // TODO:set AuthorityBinding if any 857 858 if (((Boolean) SAMLServiceManager.getAttribute( 859 SAMLConstants.SIGN_ASSERTION)).booleanValue()) 860 { 861 assertion.signXML(); 862 } 863 864 Entry entry = new Entry(assertion, destID, artString, token); 865 try { 866 Object oldEntry = null; 867 synchronized (idEntryMap) { 868 oldEntry = idEntryMap.put(aIDString, entry); 869 } 870 if (oldEntry != null) { 871 assertionTimeoutRunnable.removeElement(aIDString); 872 } 873 assertionTimeoutRunnable.addElement(aIDString); 874 if ((agent != null) && agent.isRunning() && (saml1Svc != null)) { 875 saml1Svc.incSAML1Cache(FedMonSAML1Svc.ASSERTIONS, 876 FedMonSAML1Svc.CWRITE); 877 } 878 } catch (Exception e) { 879 if (SAMLUtils.debug.messageEnabled()) { 880 SAMLUtils.debug.message("AssertionManager: couldn't add " 881 + "to idEntryMap.", e); 882 } 883 throw new SAMLResponderException( 884 SAMLUtils.bundle.getString("errorCreateAssertion")); 885 } 886 887 if (LogUtils.isAccessLoggable(java.util.logging.Level.FINER)) { 888 String[] data = { SAMLUtils.bundle.getString("assertionCreated"), 889 assertion.toString(true, true)}; 890 LogUtils.access(java.util.logging.Level.FINER, 891 LogUtils.ASSERTION_CREATED, data); 892 } else { 893 String[] data = { SAMLUtils.bundle.getString("assertionCreated"), 894 aIDString}; 895 LogUtils.access(java.util.logging.Level.INFO, 896 LogUtils.ASSERTION_CREATED, data); 897 } 898 899 if (artString != null) { 900 // put artifact in artEntryMap 901 try { 902 Object oldEntry = null; 903 synchronized (artEntryMap) { 904 oldEntry = artEntryMap.put(artString, new 905 ArtEntry(aIDString, 906 (System.currentTimeMillis() + artifactTimeout))); 907 } 908 if (oldEntry != null) { 909 artifactTimeoutRunnable.removeElement(artString); 910 } 911 artifactTimeoutRunnable.addElement(artString); 912 if ((agent != null) && agent.isRunning() && (saml1Svc != null)){ 913 saml1Svc.incSAML1Cache( 914 FedMonSAML1Svc.ARTIFACTS, 915 FedMonSAML1Svc.CWRITE); 916 } 917 } catch (Exception e) { 918 if (SAMLUtils.debug.messageEnabled()) { 919 SAMLUtils.debug.message("AssertionManager: couldn't add " 920 + "artifact to the artEntryMap.", e); 921 } 922 throw new SAMLResponderException( 923 SAMLUtils.bundle.getString("errorCreateArtifact")); 924 } 925 String[] data = {SAMLUtils.bundle.getString( 926 "assertionArtifactCreated"), artString, aIDString}; 927 LogUtils.access(java.util.logging.Level.INFO, 928 LogUtils.ASSERTION_ARTIFACT_CREATED, data); 929 } 930 931 if (token != null) { 932 // create a listener and add the listener to the token 933 AssertionSSOTokenListener listener = new AssertionSSOTokenListener( 934 aIDString, artString); 935 try { 936 sessionProvider.addListener(token, listener); 937 } catch (SessionException e) { 938 SAMLUtils.debug.error("AssertionManager.createAssertion(id):" 939 + " Couldn't add listener to session:", e); 940 } catch (UnsupportedOperationException uoe) { 941 SAMLUtils.debug.warning("AssertionManager.createAssertion(id):" 942 + " Operation add listener to session not supported:", 943 uoe); 944 } 945 } 946 947 return assertion; 948 } 949 950 /** 951 * Deletes an assertion from the server. This method is used by the 952 * AssertionSSOTokenListener and cleanup method in the package. 953 * @param assertionID the id of the Assertion to be deleted. 954 * @param artifact the artifact associated with this assertionID. 955 * When it's null, no artifact is associated with this assertionID. 956 */ 957 void deleteAssertion(String assertionID, String artifact) { 958 ArtEntry artEntry = null; 959 if (artifact != null) { 960 // this is the case when Session expired, and the assertion 961 // was created for artifact 962 artEntry = (ArtEntry) artEntryMap.remove(artifact); 963 String[] data = {SAMLUtils.bundle.getString( 964 "assertionArtifactRemoved"), artifact}; 965 LogUtils.access(java.util.logging.Level.FINE, 966 LogUtils.ASSERTION_ARTIFACT_REMOVED, data); 967 } 968 969 if (assertionID != null) { 970 Entry entry = null; 971 entry = (Entry) idEntryMap.remove(assertionID); 972 if (entry != null) { 973 String[] data = {SAMLUtils.bundle.getString("assertionRemoved"), 974 assertionID}; 975 LogUtils.access(java.util.logging.Level.FINE, 976 LogUtils.ASSERTION_REMOVED, data); 977 if (artifact == null) { 978 // this is the case when assertion expired, check to see 979 // if the assertion is associated with an artifact 980 String artString = entry.getArtifactString(); 981 if (artString != null) { 982 synchronized (artEntryMap) { 983 artEntryMap.remove(artString); 984 } 985 String[] data2 = {SAMLUtils.bundle.getString( 986 "assertionArtifactRemoved"), artifact}; 987 LogUtils.access(java.util.logging.Level.FINE, 988 LogUtils.ASSERTION_ARTIFACT_REMOVED, data2); 989 } 990 } 991 } 992 } else { 993 if ((artEntry != null) && SAMLServiceManager.getRemoveAssertion()) { 994 synchronized (idEntryMap) { 995 idEntryMap.remove(artEntry.getAssertionID()); 996 } 997 } 998 } 999 } 1000 1001 /** 1002 * Gets assertion associated with the AssertionArtifact. 1003 * @param artifact An AssertionArtifact. 1004 * @param destID A Set of String that represents the destination site id. 1005 * The destination site requesting the assertion using 1006 * the artifact. This String is compared with the destID that 1007 * the artifact is created for originally. 1008 * @param destCheckFlag true if desire to match the destionation id, 1009 * otherwise it is false. If it is false, destID can 1010 * be any string, including null. 1011 * @return The Assertion referenced to by artifact. 1012 * @throws SAMLException If an error occurred during the process, or no 1013 * assertion maps to the input artifact. 1014 */ 1015 private Assertion getAssertion(AssertionArtifact artifact, Set destID, 1016 boolean destCheckFlag) 1017 throws SAMLException { 1018 if (SAMLUtils.debug.messageEnabled()) { 1019 SAMLUtils.debug.message("getAssertion(arti): destID set= " + 1020 Base64.encode(SAMLUtils.stringToByteArray( 1021 (String)destID.iterator().next()))); 1022 } 1023 // check the destination id; also if this artifact exists 1024 String artString = artifact.getAssertionArtifact(); 1025 1026 // get server id. 1027 String remoteUrl = SAMLUtils.getServerURL( 1028 artifact.getAssertionHandle()); 1029 if (remoteUrl != null) { // not this server 1030 // call AssertionManagerClient.getAssertion 1031 if (SAMLUtils.debug.messageEnabled()) { 1032 SAMLUtils.debug.message("AssertionManager.getAssertion(art, " + 1033 "destid: calling another server in lb site:" + remoteUrl); 1034 } 1035 AssertionManagerClient amc = new AssertionManagerClient( 1036 SAMLUtils.getFullServiceURL(remoteUrl)); 1037 return amc.getAssertion(artifact, destID); 1038 } // else 1039 // get the assertion ID 1040 String aIDString = null; 1041 long timeout = 0; 1042 1043 ArtEntry artEntry = (ArtEntry) artEntryMap.get(artString); 1044 if ((agent != null) && agent.isRunning() && (saml1Svc != null)) { 1045 saml1Svc.incSAML1Cache(FedMonSAML1Svc.ARTIFACTS, 1046 FedMonSAML1Svc.CREAD); 1047 } 1048 if (artEntry == null) { 1049 if ((agent != null) && agent.isRunning() && (saml1Svc != null)) { 1050 saml1Svc.incSAML1Cache(FedMonSAML1Svc.ARTIFACTS, 1051 FedMonSAML1Svc.CMISS); 1052 } 1053 if (SAMLUtils.debug.messageEnabled()) { 1054 SAMLUtils.debug.message("AssertionManager.getAssertion(art, de" 1055 + "stid): no Assertion found corresponding to artifact."); 1056 } 1057 throw new SAMLException( 1058 SAMLUtils.bundle.getString("noMatchingAssertion")); 1059 } else { 1060 if ((agent != null) && agent.isRunning() && (saml1Svc != null)) { 1061 saml1Svc.incSAML1Cache(FedMonSAML1Svc.ARTIFACTS, 1062 FedMonSAML1Svc.CHIT); 1063 } 1064 } 1065 aIDString = (String) artEntry.getAssertionID(); 1066 if (aIDString == null) { 1067 if (SAMLUtils.debug.messageEnabled()) { 1068 SAMLUtils.debug.message("AssertionManager.getAssertion(art, de" 1069 + "stid): no AssertionID found corresponding to artifact."); 1070 } 1071 throw new SAMLException( 1072 SAMLUtils.bundle.getString("noMatchingAssertion")); 1073 } 1074 1075 timeout = artEntry.getExpireTime(); 1076 if (System.currentTimeMillis() > timeout) { 1077 if (SAMLUtils.debug.messageEnabled()) { 1078 SAMLUtils.debug.message("AssertionManager.getAssertion(art, " 1079 + "destid): artifact timed out."); 1080 } 1081 throw new SAMLException( 1082 SAMLUtils.bundle.getString("artifactTimedOut")); 1083 } 1084 1085 Entry entry = null; 1086 entry = (Entry) idEntryMap.get(aIDString); 1087 if (entry == null) { 1088 if (SAMLUtils.debug.messageEnabled()) { 1089 SAMLUtils.debug.message("AssertionManager.getAssertion(art, de" 1090 + "stid): no Entry found corresponding to artifact."); 1091 } 1092 throw new SAMLException( 1093 SAMLUtils.bundle.getString("noMatchingAssertion")); 1094 } 1095 1096 if (destCheckFlag) { 1097 // check the destination id 1098 String dest = entry.getDestID(); 1099 if (dest == null) { 1100 if (SAMLUtils.debug.messageEnabled()) { 1101 SAMLUtils.debug.message("AssertionManager.getAssertion(" + 1102 "art, destid): no destID found corresponding to artifact."); 1103 } 1104 throw new SAMLException( 1105 SAMLUtils.bundle.getString("noDestIDMatchingArtifact")); 1106 } 1107 if (destID == null || !destID.contains(dest)) { 1108 if (SAMLUtils.debug.messageEnabled()) { 1109 SAMLUtils.debug.message("AssertionManager.getAssertion(art"+ 1110 ", destid): destinationID doesn't match."); 1111 } 1112 throw new SAMLException( 1113 SAMLUtils.bundle.getString("destIDNotMatch")); 1114 } 1115 } 1116 Assertion assertion = entry.getAssertion(); 1117 if (assertion == null) { 1118 if (SAMLUtils.debug.messageEnabled()) { 1119 SAMLUtils.debug.message("AssertionManager.getAssertion(art, de" 1120 + "stid): no Assertion found corresponding to aID."); 1121 } 1122 throw new SAMLException( 1123 SAMLUtils.bundle.getString("noMatchingAssertion")); 1124 } 1125 1126 // remove the asssertion from artEntryMap 1127 synchronized (artEntryMap) { 1128 artEntryMap.remove(artString); 1129 } 1130 artifactTimeoutRunnable.removeElement(artString); 1131 String[] data = {SAMLUtils.bundle.getString( 1132 "assertionArtifactVerified"), artString}; 1133 LogUtils.access(java.util.logging.Level.INFO, 1134 LogUtils.ASSERTION_ARTIFACT_VERIFIED, data); 1135 1136 if (SAMLServiceManager.getRemoveAssertion()) { 1137 synchronized(idEntryMap) { 1138 idEntryMap.remove(aIDString); 1139 } 1140 assertionTimeoutRunnable.removeElement(aIDString); 1141 } 1142 1143 // check the time of the assertion 1144 if (!assertion.isTimeValid()) { 1145 if (SAMLUtils.debug.messageEnabled()) { 1146 SAMLUtils.debug.message("AssertionManager: assertion " 1147 + aIDString + " is expired."); 1148 } 1149 throw new SAMLException( 1150 SAMLUtils.bundle.getString("assertionTimeNotValid")); 1151 } 1152 return assertion; 1153 } 1154 1155 /** 1156 * Gets assertion associated with the AssertionArtifact. 1157 * @param artifact An AssertionArtifact. 1158 * @param destID The destination site requesting the assertion using 1159 * the artifact. This String is compared with the destID that 1160 * the artifact is created for originally. 1161 * @return The Assertion referenced to by artifact. 1162 * @throws SAMLException If an error occurred during the process, or no 1163 * assertion maps to the input artifact. 1164 */ 1165 public Assertion getAssertion(AssertionArtifact artifact, String destID) 1166 throws SAMLException { 1167 if ((artifact == null) || destID == null || destID.length() == 0) { 1168 if (SAMLUtils.debug.messageEnabled()) { 1169 SAMLUtils.debug.message("AssertionManager: input is null."); 1170 } 1171 throw new SAMLRequesterException( 1172 SAMLUtils.bundle.getString("nullInput")); 1173 } 1174 Set destSet = new HashSet(); 1175 destSet.add(destID); 1176 return getAssertion(artifact, destSet, true); 1177 } 1178 1179 /** 1180 * Gets assertion associated with the AssertionArtifact. 1181 * @param artifact An AssertionArtifact. 1182 * @param destID A Set of String that represents the destination site id. 1183 * The destination site requesting the assertion using 1184 * the artifact. Each string in this set compares with the destID 1185 * that the artifact is created for originally. If found match, 1186 * continue the operation. Otherwise, throws error. 1187 * @return The Assertion referenced to by artifact. 1188 * @throws SAMLException If an error occurred during the process, or no 1189 * assertion maps to the input artifact. 1190 */ 1191 public Assertion getAssertion(AssertionArtifact artifact, Set destID) 1192 throws SAMLException { 1193 if ((artifact == null) || destID == null || destID.isEmpty()) { 1194 if (SAMLUtils.debug.messageEnabled()) { 1195 SAMLUtils.debug.message("AssertionManager: input is null."); 1196 } 1197 throw new SAMLRequesterException( 1198 SAMLUtils.bundle.getString("nullInput")); 1199 } 1200 return getAssertion(artifact, destID, true); 1201 } 1202 1203 /** 1204 * Gets assertion associated with the AssertionArtifact. 1205 * @param artifact An AssertionArtifact. 1206 * @return The Assertion referenced to by artifact. 1207 * @throws SAMLException If an error occurred during the process, or no 1208 * assertion maps to the input artifact. 1209 */ 1210 protected Assertion getAssertion(AssertionArtifact artifact) 1211 throws SAMLException { 1212 if ((artifact == null)) { 1213 if (SAMLUtils.debug.messageEnabled()) { 1214 SAMLUtils.debug.message("AssertionManager: input is null."); 1215 } 1216 throw new SAMLRequesterException( 1217 SAMLUtils.bundle.getString("nullInput")); 1218 } 1219 return getAssertion(artifact, null, false); 1220 } 1221 1222 /** 1223 * Gets assertion created from the query. 1224 * @param query An Assertion Query. 1225 * @param destID to whom the assertion will be created for. 1226 * @return The Assertion that is created from the query. 1227 * @throws SAMLException If the Assertion cannot be created due to an 1228 * error in the query or in the receiver. 1229 */ 1230 public Assertion getAssertion(Query query, String destID) 1231 throws SAMLException { 1232 if (query == null) { 1233 if (SAMLUtils.debug.messageEnabled()) { 1234 SAMLUtils.debug.message("AssertionManager.getAssertion: input" 1235 + " query is null."); 1236 } 1237 throw new SAMLRequesterException( 1238 SAMLUtils.bundle.getString("nullInput")); 1239 } 1240 1241 Assertion result = null; 1242 int queryType = query.getQueryType(); 1243 if (queryType == Query.AUTHENTICATION_QUERY) { 1244 result = getAuthenticationAssertion((AuthenticationQuery)query, 1245 destID); 1246 } else if (queryType == Query.AUTHORIZATION_DECISION_QUERY) { 1247 result = getAuthorizationDecisionAssertion( 1248 (AuthorizationDecisionQuery)query, destID); 1249 } else if (queryType == Query.ATTRIBUTE_QUERY) { 1250 result = getAttributeAssertion((AttributeQuery)query, destID); 1251 } else { 1252 if (SAMLUtils.debug.messageEnabled()) { 1253 SAMLUtils.debug.message("AssertionManager.getAssertion: this " 1254 + "type of query is not supported:" + queryType); 1255 } 1256 throw new SAMLRequesterException( 1257 SAMLUtils.bundle.getString("queryNotSupported")); 1258 } 1259 return result; 1260 } 1261 1262 /** 1263 * Gets assertion created from an AttributeQuery. 1264 * @param query An AttributeQuery. 1265 * @param destID to whom the assertion will be created for. Currently, 1266 * it is the <code>sourceID</code> of the site that sends the query. 1267 * @return The Assertion that is created from the query. 1268 * @throws SAMLException If the Assertion cannot be created. 1269 */ 1270 private Assertion getAttributeAssertion(AttributeQuery query, String destID) 1271 throws SAMLException 1272 { 1273 if (query == null) { 1274 // no need to log the error again 1275 return null; 1276 } 1277 1278 if ((destID == null) || (destID.length() == 0)) { 1279 if (SAMLUtils.debug.messageEnabled()) { 1280 SAMLUtils.debug.message("AssertionManager.getAttributeAssertion" 1281 + ": missing destID."); 1282 } 1283 throw new SAMLException( 1284 SAMLUtils.bundle.getString("missingDestID")); 1285 } 1286 validateNumberOfAssertions(idEntryMap); 1287 Map entries = (Map) SAMLServiceManager.getAttribute( 1288 SAMLConstants.PARTNER_URLS); 1289 if (entries == null) { 1290 if (SAMLUtils.debug.messageEnabled()) { 1291 SAMLUtils.debug.message("AssertionManager.getAttributeAssertion" 1292 + ": empty partner URL list."); 1293 } 1294 throw new SAMLException( 1295 SAMLUtils.bundle.getString("emptyPartnerURLList")); 1296 } 1297 1298 SAMLServiceManager.SOAPEntry destSite = (SAMLServiceManager.SOAPEntry) 1299 entries.get(destID); 1300 AttributeMapper attrMapper = null; 1301 if ((destSite == null) || 1302 ((attrMapper = destSite.getAttributeMapper()) == null)) 1303 { 1304 if (SAMLUtils.debug.messageEnabled()) { 1305 SAMLUtils.debug.message("AssertionManager.getAttributeAssertion" 1306 + ": couldn't obtain AttributeMapper."); 1307 } 1308 throw new SAMLException( 1309 SAMLUtils.bundle.getString("errorObtainAttributeMapper")); 1310 } 1311 1312 Subject subject = query.getSubject(); 1313 String tokenID = attrMapper.getSSOTokenID(query); 1314 Object token = null; 1315 String issuerName = (String) SAMLServiceManager.getAttribute( 1316 SAMLConstants.ISSUER_NAME); 1317 if (tokenID != null) { 1318 try { 1319 if (sessionProvider == null) { 1320 throw new SAMLException(SAMLUtils.bundle.getString( 1321 "nullSessionProvider")); 1322 } 1323 token = sessionProvider.getSession(tokenID); 1324 } catch (Exception e) { 1325 if (SAMLUtils.debug.messageEnabled()) { 1326 SAMLUtils.debug.message("AssertionManager.getAttribute" 1327 + "Assertion: invalid SSO token:", e); 1328 } 1329 throw new SAMLException( 1330 SAMLUtils.bundle.getString("invalidSSOToken")); 1331 } 1332 } else { // token is null 1333 Assertion assertion = attrMapper.getSSOAssertion(query); 1334 if (assertion == null) { 1335 if (SAMLUtils.debug.messageEnabled()) { 1336 SAMLUtils.debug.message("AssertionManager.getAttribute" 1337 + "Assertion: couldn't find SSOAssertion in query."); 1338 } 1339 throw new SAMLException( 1340 SAMLUtils.bundle.getString("noSSOAssertion")); 1341 } 1342 if (!assertion.isSignatureValid()) { 1343 if (SAMLUtils.debug.messageEnabled()) { 1344 SAMLUtils.debug.message("AssertionManager.getAttribute" 1345 + "Assertion: SSOAssertion is signature invalid."); 1346 } 1347 throw new SAMLException( 1348 SAMLUtils.bundle.getString("assertionSignatureNotValid")); 1349 } 1350 if (!assertion.isTimeValid()) { 1351 if (SAMLUtils.debug.messageEnabled()) { 1352 SAMLUtils.debug.message("AssertionManager.getAttribute" 1353 + "Assertion: SSOAssertion is time invalid."); 1354 } 1355 throw new SAMLException( 1356 SAMLUtils.bundle.getString("assertionTimeNotValid")); 1357 } 1358 Iterator iter = assertion.getStatement().iterator(); 1359 Statement statement = null; 1360 Subject ssoSubject = null; 1361 while (iter.hasNext()) { 1362 statement = (Statement) iter.next(); 1363 if (statement.getStatementType() == 1364 Statement.AUTHENTICATION_STATEMENT) 1365 { 1366 ssoSubject = ((AuthenticationStatement) statement). 1367 getSubject(); 1368 break; 1369 } 1370 } 1371 if (ssoSubject == null) { 1372 if (SAMLUtils.debug.messageEnabled()) { 1373 SAMLUtils.debug.message("AssertionManager.getAttribute" 1374 + "Assertion: missing AuthenticationStatement in " 1375 + "SSOAssertion."); 1376 } 1377 throw new SAMLException( 1378 SAMLUtils.bundle.getString("noAuthNStatement")); 1379 } 1380 String issuer = assertion.getIssuer(); 1381 String aID = assertion.getAssertionID(); 1382 if ((issuerName != null) && (issuerName.equals(issuer)) && 1383 (SAMLUtils.getServerURL(aID) == null)) 1384 { 1385 // this server is the issuer 1386 if (SAMLUtils.debug.messageEnabled()) { 1387 SAMLUtils.debug.message("AssertionManager.getAttrAssertion:" 1388 + "this server is the issuer."); 1389 } 1390 Entry entry = (Entry) idEntryMap.get(aID); 1391 if ((agent != null) && agent.isRunning() && (saml1Svc != null)){ 1392 saml1Svc.incSAML1Cache( 1393 FedMonSAML1Svc.ASSERTIONS, 1394 FedMonSAML1Svc.CREAD); 1395 } 1396 if (entry != null) { 1397 token = entry.getSSOToken(); 1398 if (token != null) { 1399 verifySSOTokenAndNI(token, 1400 ssoSubject.getNameIdentifier()); 1401 } 1402 if ((agent != null) && 1403 agent.isRunning() && 1404 (saml1Svc != null)) 1405 { 1406 saml1Svc.incSAML1Cache( 1407 FedMonSAML1Svc.ASSERTIONS, 1408 FedMonSAML1Svc.CHIT); 1409 } 1410 } else { 1411 if ((agent != null) && 1412 agent.isRunning() && 1413 (saml1Svc != null)) 1414 { 1415 saml1Svc.incSAML1Cache( 1416 FedMonSAML1Svc.ASSERTIONS, 1417 FedMonSAML1Svc.CMISS); 1418 } 1419 } 1420 } else { // this machine is not the issuer 1421 if (SAMLUtils.debug.messageEnabled()) { 1422 SAMLUtils.debug.message("AssertionManager.getAttrAssertion:" 1423 + "this server is not the issuer."); 1424 } 1425 token = checkAssertionAndCreateSSOToken(assertion, null, 1426 ssoSubject); 1427 } 1428 } 1429 1430 // get here then got a valid token 1431 List attributes = attrMapper.getAttributes(query, destID, token); 1432 if ((attributes == null) || (attributes.size() == 0)) { 1433 return null; 1434 } 1435 1436 Set stmtSet = new HashSet(); 1437 stmtSet.add(new AttributeStatement(subject, attributes)); 1438 Date issueInstant = new Date(); 1439 Date notBefore = new Date(issueInstant.getTime() - notBeforeSkew); 1440 Date notAfter = new Date(issueInstant.getTime() + assertionTimeout); 1441 Conditions cond = new Conditions(notBefore, notAfter); 1442 Assertion newAssertion = new Assertion(null, issuerName, issueInstant, 1443 cond, stmtSet); 1444 if (((Boolean) SAMLServiceManager.getAttribute( 1445 SAMLConstants.SIGN_ASSERTION)).booleanValue()) 1446 { 1447 newAssertion.signXML(); 1448 } 1449 String aIDString = newAssertion.getAssertionID(); 1450 // don't save the token and don't add listener 1451 Entry newEntry = new Entry(newAssertion, destID, null, null); 1452 1453 // add newEntry to idEntryMap 1454 try { 1455 Object oldEntry = null; 1456 synchronized (idEntryMap) { 1457 oldEntry = idEntryMap.put(aIDString, newEntry); 1458 } 1459 if (oldEntry != null) { 1460 assertionTimeoutRunnable.removeElement(aIDString); 1461 } 1462 assertionTimeoutRunnable.addElement(aIDString); 1463 if ((agent != null) && agent.isRunning() && (saml1Svc != null)) { 1464 saml1Svc.incSAML1Cache(FedMonSAML1Svc.ASSERTIONS, 1465 FedMonSAML1Svc.CWRITE); 1466 } 1467 } catch (Exception e) { 1468 if (SAMLUtils.debug.messageEnabled()) { 1469 SAMLUtils.debug.message("AssertionManager.getAttributeAssertion" 1470 + " couldn't add assertion to the idEntryMap.", e); 1471 } 1472 } 1473 1474 if (LogUtils.isAccessLoggable(java.util.logging.Level.FINER)) { 1475 String[] data = { SAMLUtils.bundle.getString("assertionCreated"), 1476 newAssertion.toString(true, true)}; 1477 LogUtils.access(java.util.logging.Level.FINER, 1478 LogUtils.ASSERTION_CREATED, data); 1479 } else { 1480 String[] data = { SAMLUtils.bundle.getString("assertionCreated"), 1481 aIDString}; 1482 LogUtils.access(java.util.logging.Level.INFO, 1483 LogUtils.ASSERTION_CREATED, data); 1484 } 1485 1486 return newAssertion; 1487 } 1488 1489 /** 1490 * Gets assertion created from an AuthenticationQuery. 1491 * @param query An AuthenticationQuery. 1492 * @param destID to whom the assertion will be created for. 1493 * @return The Assertion that is created from the query. 1494 * @throws SAMLException If the Assertion cannot be created. 1495 */ 1496 private Assertion getAuthenticationAssertion( 1497 AuthenticationQuery query, String destID) throws SAMLException 1498 { 1499 if (query == null) { 1500 // no need to log the error again 1501 return null; 1502 } 1503 validateNumberOfAssertions(idEntryMap); 1504 1505 // get the subject of the query 1506 Subject subject = query.getSubject(); 1507 1508 // get SubjectConfirmation 1509 SubjectConfirmation sc = subject.getSubjectConfirmation(); 1510 if (sc == null) { 1511 if (SAMLUtils.debug.messageEnabled()) { 1512 SAMLUtils.debug.message("AssertionManager.getAuthNAssertion:" 1513 + " missing SubjectConfirmation."); 1514 } 1515 // since we couldn't find the SSOToken in SubjectConfirmationData 1516 // we don't know if the subject is authenticated to OpenSSO 1517 // Enterprise. 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 = new Date(); 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 = new Date(); 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 = System.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}
Copyright © 2010-2017, ForgeRock All Rights Reserved.