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




























































Copyright © 2010-2017, ForgeRock All Rights Reserved.