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: SAML2SDKUtils.java,v 1.12 2008/08/31 05:49:48 bina Exp $
026 *
027 */
028
029
030package com.sun.identity.saml2.common;
031
032import com.sun.identity.liberty.ws.disco.ResourceOffering;
033import com.sun.identity.liberty.ws.security.SecurityAssertion;
034import com.sun.identity.plugin.session.SessionManager;
035import com.sun.identity.plugin.session.SessionProvider;
036import com.sun.identity.saml.common.SAMLConstants;
037import com.sun.identity.saml.common.SAMLUtilsCommon;
038import com.sun.identity.saml2.jaxb.entityconfig.BaseConfigType;
039import com.sun.identity.saml2.meta.SAML2MetaUtils;
040import com.sun.identity.shared.configuration.SystemPropertiesManager;
041import com.sun.identity.shared.debug.Debug;
042import com.sun.identity.shared.locale.Locale;
043import com.sun.identity.shared.xml.XMLUtils;
044import java.security.SecureRandom;
045import java.lang.reflect.Constructor;
046import java.lang.reflect.InvocationTargetException;
047import java.util.ArrayList;
048import java.util.HashMap;
049import java.util.List;
050import java.util.Map;
051import java.util.ResourceBundle;
052import javax.servlet.http.HttpServletRequest;
053import org.w3c.dom.Attr;
054import org.w3c.dom.Element;
055import org.w3c.dom.NamedNodeMap;
056import javax.xml.soap.SOAPException;
057
058/**
059 * The <code>SAML2SDKUtils</code> contains utility methods for SAML 2.0
060 * implementation.
061 *
062 * @supported.all.api
063 */
064public class SAML2SDKUtils {
065    //
066    // This utility class will be run on client side as well,
067    // so DO NOT add any static block which will not run on client side.
068    //
069    // The deugging instance
070    public static Debug debug = Debug.getInstance("libSAML2");
071    //  SAML2 Resource bundle
072    public static final String BUNDLE_NAME = "libSAML2";
073    // The resource bundle for SAML 2.0 implementation.
074    public static ResourceBundle bundle = Locale.
075        getInstallResourceBundle(BUNDLE_NAME);
076    protected static final String SAML2ID_PREFIX = "s2";
077    public static SecureRandom random = new SecureRandom();
078
079    /**
080     * Defines mapping between interface and implementation class,
081     * the properties are read from AMConfig.properties in following format:
082     * com.sun.identity.saml2.sdk.mapping.<interface>=<implementation_class>
083     * e.g.
084     * com.sun.identity.saml2.sdk.mapping.Assertion=com.xxx.saml2.AssertionImpl
085     */
086    private static Map classMapping = new HashMap();
087
088    // define constants for the interface names
089    public static final String ACTION = "Action"; 
090    public static final String ADVICE = "Advice"; 
091    public static final String ASSERTION = "Assertion";
092    public static final String ASSERTION_ID_REF = "AssertionIDRef";
093    public static final String ASSERTION_ID_REQUEST = "AssertionIDRequest";
094    public static final String ATTRIBUTE = "Attribute"; 
095    public static final String ATTRIBUTE_STATEMENT = "AttributeStatement";
096    public static final String AUDIENCE_RESTRICTION = "AudienceRestriction"; 
097    public static final String AUTHN_CONTEXT = "AuthnContext"; 
098    public static final String AUTHN_STATEMENT = "AuthnStatement"; 
099    public static final String AUTHZ_DECISION_STATEMENT = 
100        "AuthzDecisionStatement"; 
101    public static final String BASEID = "BaseID"; 
102    public static final String CONDITION = "Condition"; 
103    public static final String CONDITIONS = "Conditions"; 
104    public static final String ENCRYPTED_ASSERTION = "EncryptedAssertion";
105    public static final String ENCRYPTED_ATTRIBUTE = "EncryptedAttribute"; 
106    public static final String ENCRYPTED_ELEMENT = "EncryptedElement"; 
107    public static final String ENCRYPTEDID = "EncryptedID"; 
108    public static final String EVIDENCE = "Evidence";
109    public static final String ISSUER = "Issuer"; 
110    public static final String KEYINFO_CONFIRMATION_DATA = 
111        "KeyInfoConfirmationData"; 
112    public static final String NAMEID = "NameID"; 
113    public static final String ONE_TIME_USE = "OneTimeUse"; 
114    public static final String PROXY_RESTRICTION = "ProxyRestriction"; 
115    public static final String STATEMENT = "Statement"; 
116    public static final String SUBJECT_CONFIRMATION_DATA = 
117        "SubjectConfirmationData"; 
118    public static final String SUBJECT_CONFIRMATION = "SubjectConfirmation"; 
119    public static final String SUBJECT = "Subject";
120    public static final String SUBJECT_LOCALITY = "SubjectLocality"; 
121    public static final String ARTIFACT = "Artifact"; 
122    public static final String ARTIFACT_RESOLVE = "ArtifactResolve"; 
123    public static final String ARTIFACT_RESPONSE = "ArtifactResponse";
124    public static final String ATTRIBUTE_QUERY = "AttributeQuery";
125    public static final String AUTHN_QUERY = "AuthnQuery";
126    public static final String AUTHN_REQUEST = "AuthnRequest";
127    public static final String ECP_RELAY_STATE = "ECPRelayState";
128    public static final String ECP_REQUEST = "ECPRequest";
129    public static final String ECP_RESPONSE = "ECPResponse";
130    public static final String EXTENSIONS = "Extensions"; 
131    public static final String GET_COMPLETE = "GetComplete"; 
132    public static final String IDPENTRY = "IDPEntry"; 
133    public static final String IDPLIST = "IDPList";
134    public static final String LOGOUT_REQUEST = "LogoutRequest"; 
135    public static final String LOGOUT_RESPONSE = "LogoutResponse"; 
136    public static final String MANAGE_NAMEID_REQUEST = "ManageNameIDRequest"; 
137    public static final String MANAGE_NAMEID_RESPONSE = "ManageNameIDResponse"; 
138    public static final String NAMEID_POLICY = "NameIDPolicy"; 
139    public static final String NEW_ENCRYPTEDID = "NewEncryptedID"; 
140    public static final String NEWID = "NewID";
141    public static final String REQUESTED_AUTHN_CONTEXT = 
142        "RequestedAuthnContext"; 
143    public static final String REQUESTERID = "RequesterID"; 
144    public static final String RESPONSE = "Response";
145    public static final String SCOPING = "Scoping"; 
146    public static final String SESSION_INDEX = "SessionIndex"; 
147    public static final String STATUS_CODE = "StatusCode"; 
148    public static final String STATUS_DETAIL = "StatusDetail"; 
149    public static final String STATUS = "Status";
150    public static final String STATUS_MESSAGE = "StatusMessage"; 
151    public static final String STATUS_RESPONSE = "StatusResponse"; 
152    public static final String NAMEIDMAPPING_REQ = "NameIDMappingRequest"; 
153    public static final String NAMEIDMAPPING_RES = "NameIDMappingResponse"; 
154
155    /**
156     * List of Interfaces in assertion and protocol packages which could have 
157     * customized implementation
158     */
159    private static String[] interfactNames = {
160        ACTION, ADVICE, ASSERTION, ASSERTION_ID_REF, ASSERTION_ID_REQUEST,
161        ATTRIBUTE, ATTRIBUTE_STATEMENT, AUDIENCE_RESTRICTION, AUTHN_CONTEXT,
162        AUTHN_STATEMENT, AUTHZ_DECISION_STATEMENT, BASEID, 
163        CONDITION, CONDITIONS, ENCRYPTED_ASSERTION,
164        ENCRYPTED_ATTRIBUTE, ENCRYPTED_ELEMENT, ENCRYPTEDID, EVIDENCE,
165        ISSUER, KEYINFO_CONFIRMATION_DATA, NAMEID,
166        ONE_TIME_USE, PROXY_RESTRICTION, STATEMENT, 
167        SUBJECT_CONFIRMATION_DATA, SUBJECT_CONFIRMATION, SUBJECT,
168        SUBJECT_LOCALITY, ARTIFACT, ARTIFACT_RESOLVE, ARTIFACT_RESPONSE,
169        ATTRIBUTE_QUERY, AUTHN_QUERY, AUTHN_REQUEST, EXTENSIONS, GET_COMPLETE,
170        IDPENTRY, IDPLIST, LOGOUT_REQUEST, LOGOUT_RESPONSE,
171        MANAGE_NAMEID_REQUEST, MANAGE_NAMEID_RESPONSE, NAMEID_POLICY,
172        NEW_ENCRYPTEDID, NEWID, REQUESTED_AUTHN_CONTEXT, REQUESTERID, RESPONSE,
173        SCOPING, SESSION_INDEX, STATUS_CODE, STATUS_DETAIL, STATUS,
174        STATUS_MESSAGE, STATUS_RESPONSE, NAMEIDMAPPING_REQ, NAMEIDMAPPING_RES}; 
175
176    /**
177     * Class array for Artifact constructor
178     */
179    private static Class[] artParam = new Class[] { (new byte[2]).getClass(), 
180        int.class, String.class, String.class };
181
182    /**
183     * Class array for String as parameter
184     */
185    private static Class[] stringParam = new Class[] {String.class};
186
187    /**
188     * Class array for Element as parameter
189     */
190    private static Class[] elementParam = new Class[] {Element.class};
191
192    static {
193        // initialize class mapper
194        int len = interfactNames.length;
195        for (int i = 0; i < len; i++) {
196            String iName = interfactNames[i];
197            try {
198                String implClass = SystemPropertiesManager.get(
199                    SAML2Constants.SDK_CLASS_MAPPING + iName);
200                if (implClass != null && implClass.trim().length() != 0) {
201                    // try it out
202                    if (debug.messageEnabled()) {
203                        debug.message("SAML2SDKUtils.init: mapper for " + iName
204                            + "=" + implClass);
205                    }
206                    classMapping.put(iName, Class.forName(implClass.trim()));
207                }
208            } catch (ClassNotFoundException cnfe) {
209                debug.error("SAML2SDKUtils.init: " + iName, cnfe);
210            } 
211        }
212    }
213    
214    /**
215     * Protected contstructor.
216     */
217    protected SAML2SDKUtils() {}
218     
219    /**
220     * Returns default object instance for a given interface. 
221     * @param iName name of the interface.
222     * @return object instance corresponding to the interface implementation. 
223     *         return null if the object instance could not be obtained.
224     */
225    public static Object getObjectInstance(String iName) {
226        Class implClass = (Class) classMapping.get(iName);
227        if (implClass == null) {
228            return null;
229        } else {
230            try {
231                return implClass.newInstance();
232            } catch (InstantiationException ie) {
233                debug.error("SAML2SDKUtils.getDefaultInstance: " + iName, ie);
234            } catch (IllegalAccessException iae) {
235                debug.error("SAML2SDKUtils.getDefaultInstance: " + iName, iae);
236            } 
237            return null;
238        }
239    }
240
241    /**
242     * Returns new object instance taking String parameter in constructor. 
243     * @param iName name of the interface.
244     * @param value String value to be used as parameter in constructor.
245     * @return object instance corresponding to the interface implementation. 
246     *         return null if the object instance could not be obtained.
247     */
248    public static Object getObjectInstance(String iName, String value){
249        Class implClass = (Class) classMapping.get(iName);
250        if (implClass == null) {
251            return null;
252        } else {
253            if (debug.messageEnabled()) {
254                debug.message("SAML2SDKUtils.getObjectInstance: new customized "
255                    + "impl (String) instance for " + iName);
256            }
257            Object[] params = new Object[] { value }; 
258            return getObjectInstance(implClass, stringParam, params);
259        }
260    }
261
262    /**
263     * Returns new object instance taking Element parameter in constructor. 
264     * @param iName name of the interface.
265     * @param value Element value to be used as parameter in constructor.
266     * @return object instance corresponding to the interface implementation. 
267     *         return null if the object instance could not be obtained.
268     */
269    public static Object getObjectInstance(String iName, Element value) {
270        Class implClass = (Class) classMapping.get(iName);
271        if (implClass == null) {
272            return null;
273        } else {
274            if (debug.messageEnabled()) {
275                debug.message("SAML2SDKUtils.getObjectInstance: new customized "
276                    + "impl instance (Element) for " + iName);
277            }
278            Object[] params = new Object[] { value }; 
279            return getObjectInstance(implClass, elementParam, params);
280        }
281    }
282
283    /**
284     * Returns new object instance with given parameters. 
285     * @param iName name of the interface.
286     * @param typecode type code.
287     * @param endpointIndex end point index.
288     * @param sourceID source ID.
289     * @param messageHandle message handler.
290     * @return object instance corresponding to the interface implementation. 
291     *         return null if the object instance could not be obtained.
292     */
293
294    public static Object getObjectInstance(String iName, byte[] typecode,
295        int endpointIndex, String sourceID, String messageHandle) {
296        Class implClass = (Class) classMapping.get(iName);
297        if (implClass == null) {
298            return null;
299        } else {
300            if (debug.messageEnabled()) {
301                debug.message("SAML2SDKUtils.getObjectInstance: new customized "
302                    + "impl (4) instance for " + iName);
303            }
304            Object[] params = new Object[] 
305                { typecode, new Integer(endpointIndex), 
306                  sourceID, messageHandle }; 
307            return getObjectInstance(implClass, artParam, params);
308        }
309    }
310
311
312    /**
313     * Returns new object instance with given parameter in constructor. 
314     * @param impl Class instance.
315     * @param paramObj Class array for constructor parameters.
316     * @param valueObj Object array for values of constructor parameters.
317     * @return object instance corresponding to the interface implementation. 
318     *         return null if the object instance could not be obtained.
319     */
320    private static Object getObjectInstance(Class impl, 
321        Class[] paramObj, Object[] valueObj) {
322        try {
323            Constructor constr = impl.getConstructor(paramObj);
324            return constr.newInstance(valueObj);
325        } catch (NoSuchMethodException nsme) {
326            debug.error("SAML2SDKUtils.getObjectInstance: " + impl.getName(), 
327                nsme);
328        } catch (SecurityException se) {
329            debug.error("SAML2SDKUtils.getObjectInstance: " + impl.getName(), 
330                se);
331        } catch (InstantiationException ie) {
332            debug.error("SAML2SDKUtils.getObjectInstance: " + impl.getName(), 
333                ie);
334        } catch (IllegalAccessException iae) {
335            debug.error("SAML2SDKUtils.getObjectInstance: " + impl.getName(), 
336                iae);
337        } catch (IllegalArgumentException iae) {
338            debug.error("SAML2SDKUtils.getObjectInstance: " + impl.getName(), 
339                iae);
340        } catch (InvocationTargetException ite) {
341            debug.error("SAML2SDKUtils.getObjectInstance: " + impl.getName(), 
342                ite);
343        } 
344        return null;
345    }
346
347    /**
348     * Verifies if an element is a type of a specific statement.
349     * Currently, this method is used by class AuthnStatementImpl,
350     * AuthzDecisionStatement and AttributeStatementImpl.
351     * @param element a DOM Element which needs to be verified.
352     * @param statementname A specific name of a statement, for example,
353     *          AuthnStatement, AuthzStatement or AttributeStatement
354     * @return <code>true</code> if the element is of the specific type;
355     *          <code>false</code> otherwise.
356     */
357    public static boolean checkStatement(Element element, String statementname){
358        if (element == null || statementname == null) {
359            return false;
360        }
361        
362        String tag = element.getLocalName();
363        if (tag == null) {
364            return false;
365        } else if (tag.equals("Statement")) {
366            NamedNodeMap nm = element.getAttributes();
367            int len = nm.getLength();
368            String attrName = null;
369            Attr attr = null;
370            for (int j = 0; j < len; j++) {
371                attr = (Attr) nm.item(j);
372                attrName = attr.getLocalName();
373                if ((attrName != null) && (attrName.equals("type")) &&
374                (attr.getNodeValue().equals(statementname + "Type"))) {
375                    return true;
376                }
377            }
378        } else if (tag.equals(statementname)) {
379            return true;
380        }
381        return false;
382    }   
383
384    /**
385     * Converts byte array to String.
386     *
387     * @param bytes     Byte Array to be converted.
388     * @return          result of the conversion.
389     */
390    public static String byteArrayToString(byte[] bytes) {
391        char chars[] = new char[bytes.length];
392        for (int i = 0; i < bytes.length; i++) {
393            chars[i] = (char) bytes[i];
394        }
395        return new String(chars);
396    }
397
398    /**
399     * Converts integer to byte array.
400     *
401     * @param i         an integer value between 0 and 65535.
402     * @return          a byte array whose length is 2.
403     * @throws SAML2Exception if the input is not between 0 and 65535.
404     */
405    public static byte[] intToTwoBytes(int i)
406    throws SAML2Exception {
407        if (i < 0 || i > 65535) {
408            debug.error("SAML2Utils.intToTwoBytes: wrong index value range.");
409            throw new SAML2Exception(
410            bundle.getString("wrongInput"));
411        }
412        
413        String hexStr = Integer.toHexString(i);
414        
415        //System.out.println("Original="+hexStr);
416        
417        int len = hexStr.length();
418        String norm = null;
419        if (len > 4) {
420            norm = hexStr.substring(0,4);
421        } else {
422            switch (len) {
423                case 1:
424                    norm = "000"+hexStr;
425                    break;
426                case 2:
427                    norm = "00"+hexStr;
428                    break;
429                case 3:
430                    norm = "0"+hexStr;
431                    break;
432                default:
433                    norm = hexStr;
434            }
435        }
436        
437        byte[] bytes = hexStringToByteArray(norm);
438        
439        return bytes;
440    }
441    
442    /**
443     * Converts two bytes to an integer.
444     *
445     * @param bytes     byte array whose length is 2.
446     * @return          an integer value between 0 and 65535.
447     * @throws SAML2Exception if the input is null or the length is not 2.
448     */
449    public static int twoBytesToInt(byte[] bytes)
450    throws SAML2Exception {
451        if (bytes == null || bytes.length != 2) {
452            debug.error("SAML2Utils.twoBytesToInt: input is null or length is "
453            + "not 2.");
454            throw new SAML2Exception(bundle.getString("wrontInput"));
455        }
456        
457        String str0 = Integer.toHexString(bytes[0]);
458        int len0 = str0.length();
459        String norm0 = null;
460        if (len0 > 2) {
461            norm0 = str0.substring(len0-2, len0);
462        } else {
463            norm0 = str0;
464        }
465        String str1 = Integer.toHexString(bytes[1]);
466        int len1 = str1.length();
467        String norm1 = null;
468        if (len1 > 2) {
469            norm1 = str1.substring(len1-2, len1);
470        } else if (len1 == 1) {
471            norm1 = "0"+str1;
472        } else {
473            norm1 = str1;
474        }
475        
476        String wholeHexStr = norm0+norm1;
477        
478        int i = Integer.parseInt(wholeHexStr, 16);
479        
480        return i;
481    }
482    
483    /**
484     * Generates message handle used in an <code>Artifact</code>.
485     *
486     * @return          String format of 20-byte sequence identifying
487     *                  a message.
488     */
489    public static String generateMessageHandle() {
490        if (random == null) {
491            return null;
492        }
493        byte bytes[] = new byte[SAML2Constants.ID_LENGTH];
494        random.nextBytes(bytes);
495        return byteArrayToString(bytes);
496    }
497    
498    /**
499     * Converts String to Byte Array.
500     *
501     * @param input     String to be converted.
502     * @return          result of the conversion.
503     */
504    public static byte[] stringToByteArray(String input) {
505        char chars[] = input.toCharArray();
506        byte bytes[] = new byte[chars.length];
507        for (int i = 0; i < chars.length; i++) {
508            bytes[i] = (byte) chars[i];
509        }
510        return bytes;
511    }
512    
513    /**
514     * Converts byte array to <code>Hex</code> String.
515     *
516     * @param byteArray Byte Array to be converted.
517     * @return result of the conversion.
518     */
519    public static String byteArrayToHexString(byte[] byteArray) {
520        int readBytes = byteArray.length;
521        StringBuffer hexData = new StringBuffer();
522        int onebyte;
523        for (int i=0; i < readBytes; i++) {
524            onebyte = ((0x000000ff & byteArray[i]) | 0xffffff00);
525            hexData.append(Integer.toHexString(onebyte).substring(6));
526        }
527        return hexData.toString();
528    }
529    
530    /**
531     * Converts <code>Hex</code> String to Byte Array.
532     *
533     * @param hexString <code>Hex</code> String to be converted.
534     * @return result of the conversion.
535     */
536    public static byte[] hexStringToByteArray(String hexString) {
537        int read = hexString.length();
538        byte[] byteArray = new byte[read/2];
539        for (int i=0, j=0; i < read; i++, j++) {
540            String part = hexString.substring(i,i+2);
541            byteArray[j] =
542            new Short(Integer.toString(Integer.parseInt(part,16))).
543            byteValue();
544            i++;
545        }
546        return byteArray;
547    }
548    
549    /**
550     * Generates ID.
551     * @return ID value.
552     */
553    public static String generateID() {
554        if (random == null) {
555            return null;
556        }
557        byte bytes[] = new byte[SAML2Constants.ID_LENGTH];
558        random.nextBytes(bytes);
559        return (SAML2ID_PREFIX + byteArrayToHexString(bytes));
560    }    
561
562    /**
563     * Gets the Discovery bootstrap resource offering in an attribute
564     * statement. After a single sign-on with an Identity Provider, a service
565     * provider may get Discovery service esource Offerings through a SAML2
566     * assertion. This APIs helps in retrieving the resource offerings
567     * if the user has been authenticated through the SAML2 SSO. It will
568     * need to have a valid single sign on token (generated through the
569     * SAML2 SSO).
570     *
571     * @param request <code>HttpServletRequest</code> associated with a user
572     *        session.
573     * @return <code>ResourceOffering</code> Discovery Resource Offering,
574     *         null if there is any failure  or if there is not one
575     */
576    public static ResourceOffering getDiscoveryBootStrapResourceOffering(
577        HttpServletRequest request) {
578
579        if (request == null) {
580            if (debug.messageEnabled()) {
581                debug.message("SAML2Utils.getDiscoveryBootStrapResource" +
582                    "Offerings: null Input params");
583            }
584            return null;
585        }
586        try {
587            SessionProvider sessionProvider = SessionManager.getProvider();
588            Object session = sessionProvider.getSession(request);
589
590            String[] roStr = sessionProvider.getProperty(session,
591                SAML2Constants.DISCOVERY_BOOTSTRAP_ATTRIBUTE_NAME);
592            if ((roStr == null) || (roStr.length == 0)) {
593                return null;
594            }
595
596            return new ResourceOffering(
597                XMLUtils.toDOMDocument(roStr[0], debug).getDocumentElement());
598
599        } catch(Exception ex) {
600            debug.error("SAML2Utils.getDiscoveryBootStrapResourceOfferings: " +
601                " Exception while retrieving discovery boot strap info.", ex);
602            return null;
603        }
604       
605    }
606    
607    /**
608     * Gets the Discovery bootstrap credentials.
609     * After a single sign-on with an Identity Provider, a service
610     * provider may get Discovery bootstrap resource offerings and credentials
611     * through a SAML assertion. This APIs helps in retrieving the credentials
612     * if the user has been authenticated through the SAML2 SSO. It will
613     * need to have a valid single sign on token (generated through the
614     * SAML2 SSO).
615     *
616     * @param request <code>HttpServletRequest</code> associated with a user
617     *     session.
618     * @return <code>List</code> of <code>SecurityAssertions</code>,
619     *     null if there is any failure  or if there is not one
620     */
621    public static List getDiscoveryBootStrapCredentials(
622        HttpServletRequest request) {
623  
624        if (request == null) {
625            if (debug.messageEnabled()) {
626                debug.message("SAML2Utils.getDiscoveryBootStrapCredentials: " +
627                    " null Input params");
628            }
629            return null;
630        }
631        try {
632            SessionProvider sessionProvider = SessionManager.getProvider();
633            Object session = sessionProvider.getSession(request);
634            String[] credentials = sessionProvider.getProperty(session,
635                SAML2Constants.DISCOVERY_BOOTSTRAP_CREDENTIALS);
636            if ((credentials == null) || (credentials.length == 0)) {
637                return null;
638            }
639
640            List securityAssertions = new ArrayList(); 
641            for(int i=0; i< credentials.length; i++) {
642                SecurityAssertion securityAssertion = new SecurityAssertion(
643                    XMLUtils.toDOMDocument(credentials[i], debug)
644                    .getDocumentElement());
645                securityAssertions.add(securityAssertion);
646            }
647            return securityAssertions;
648        } catch(Exception ex) {
649            debug.error("SAML2Utils.getDiscoveryBootStrapCredentials: ", ex);
650            return null;
651        }
652    }
653
654    /**
655     * Creates <code>SOAPMessage</code> with the input XML String
656     * as message body.
657     * @param xmlString XML string to be put into <code>SOAPMessage</code> body.
658     * @return newly created <code>SOAPMessage</code>.
659     * @exception SOAPException if it cannot create the
660     *            <code>SOAPMessage</code>.
661     */
662    public static String createSOAPMessageString(String xmlString)
663    throws SOAPException, SAML2Exception {
664            StringBuffer sb = new StringBuffer(500);
665            if (debug.messageEnabled()) {
666                debug.message("SAML2Utils.createSOAPMessage: xmlstr = " +
667                        xmlString);
668            }
669            sb.append("<").append(SAMLConstants.SOAP_ENV_PREFIX).
670                    append(":Envelope").append(SAMLConstants.SPACE).
671                    append("xmlns:").append(SAMLConstants.SOAP_ENV_PREFIX).
672                    append("=\"").append(SAMLConstants.SOAP_URI).append("\">").
673                    append("<").
674                    append(SAMLConstants.SOAP_ENV_PREFIX).append(":Body>").
675                    append(xmlString).
676                    append(SAMLConstants.START_END_ELEMENT).
677                    append(SAMLConstants.SOAP_ENV_PREFIX).
678                    append(":Body>").
679                    append(SAMLConstants.START_END_ELEMENT).
680                    append(SAMLConstants.SOAP_ENV_PREFIX).
681                    append(":Envelope>").append(SAMLConstants.NL);
682
683            if (debug.messageEnabled()) {
684                debug.message("SAML2Utils.createSOAPMessage: soap message = " +
685                        sb.toString());
686            }
687        return sb.toString();
688     }
689    
690    
691    /**
692     * Fills in basic auth user and password inside the location URL
693     * if configuration is done properly
694     * @param config Either an SPSSOConfigElement object , an
695     *               IDPSSOConfigElement object or PEPConfigElement.
696     * @param locationURL The original location URL which is to be
697     *                    inserted with user:password@ before the
698     *                    hostname part and after //
699     * @return The modified location URL with the basic auth user
700     *         and password if configured properly
701     */
702    public static String fillInBasicAuthInfo(
703            BaseConfigType config,
704            String locationURL) {
705
706        if (config == null) {
707            return locationURL;
708        }
709        Map map = SAML2MetaUtils.getAttributes(config);
710        List baoList = (List)map.get(
711                SAML2Constants.BASIC_AUTH_ON);
712        if (baoList == null || baoList.isEmpty()) {
713            return locationURL;
714        }
715        String on = (String)baoList.get(0);
716        if (on == null) {
717            return locationURL;
718        }
719        on = on.trim();
720        if (on.length() == 0 || !on.equalsIgnoreCase("true")) {
721            return locationURL;
722        }
723        List ul =  (List)map.get(
724                SAML2Constants.BASIC_AUTH_USER);
725  
726        if (ul == null || ul.isEmpty()) {
727            return locationURL;
728        }
729        String u = (String) ul.get(0);
730        if (u == null) {
731            return locationURL;
732        }
733        u = u.trim();
734        if (u.length() == 0) {
735            return locationURL;
736        }
737        List pl = (List)map.get(
738                SAML2Constants.BASIC_AUTH_PASSWD);
739        String p = null;
740        if (pl != null && !pl.isEmpty()) {
741            p = (String) pl.get(0);
742        }
743        if (p == null) {
744            p = "";
745        }
746
747        String dp = SAMLUtilsCommon.decodePassword(p);
748
749        int index = locationURL.indexOf("//");
750        return locationURL.substring(0, index+2) +
751                u + ":" + dp + "@" +
752                locationURL.substring(index+2);
753    }
754
755    /**
756     * Converts a value of XML boolean type to Boolean object.
757     *
758     * @param str a value of XML boolean type
759     * @return a Boolean object.
760     * @throws SAML2Exception if there is a syntax error
761     */
762    public static Boolean StringToBoolean(String str) throws SAML2Exception {
763        if (str == null) {
764            return null;
765        }
766        
767        if (str.equals("true") || str.equals("1")) {
768            return Boolean.TRUE;
769        }
770        
771        if (str.equals("false") || str.equals("0")) {
772            return Boolean.FALSE;
773        }
774        
775        throw new SAML2Exception(SAML2SDKUtils.bundle.getString(
776            "invalidXMLBooleanValue"));
777    }
778
779    /**
780     * Removes deployment URI from the pass down string. i.e.
781     * from "/opensso/ArtifactResolver/metaAlias/idp" to
782     * "/ArtifactResolver/metaAlias/idp".
783     * @param uri the URI string which the deployment uri is to be removed
784     * return string without deployment uri
785     */
786    public static String removeDeployUri(String uri) {
787        if ((uri == null) || (uri.length() == 0)) {
788            return uri;
789        }
790        int loc = uri.indexOf("/", 1);
791        if (loc == -1) {
792            return null;
793        } else {
794            return uri.substring(loc);
795        }
796    }
797
798    /**
799     * Returns the boolean value as a <code>Boolean</code> object.
800     *
801     * @param value boolean value true or false.
802     *
803     */
804    public static Boolean booleanValueOf(String value) {
805        return new Boolean("true".equalsIgnoreCase(value) || "1".equals(value));
806    }
807}




























































Copyright © 2010-2017, ForgeRock All Rights Reserved.