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