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: SecurityTokenManagerClient.java,v 1.9 2008/08/19 19:11:09 veiming Exp $
026 *
027 */
028
029/*
030 * Portions Copyright 2013 ForgeRock AS
031 */
032package com.sun.identity.liberty.ws.security;
033
034import com.sun.identity.shared.locale.Locale;
035import com.sun.identity.shared.configuration.SystemPropertiesManager;
036import com.sun.identity.shared.xml.XMLUtils;
037
038import com.sun.identity.common.SystemConfigurationUtil;
039import com.sun.identity.shared.encode.Base64;
040import com.sun.identity.shared.encode.Base64;
041
042import com.sun.identity.liberty.ws.common.wsse.BinarySecurityToken;
043import com.sun.identity.liberty.ws.disco.EncryptedResourceID;
044
045import com.sun.identity.plugin.session.SessionManager;
046import com.sun.identity.saml.assertion.Assertion;
047import com.sun.identity.saml.assertion.AssertionIDReference;
048import com.sun.identity.saml.assertion.Attribute;
049import com.sun.identity.saml.assertion.NameIdentifier;
050import com.sun.identity.saml.common.SAMLConstants;
051import com.sun.identity.saml.common.SAMLException;
052import com.sun.identity.saml.common.SAMLUtils;
053import com.sun.identity.shared.jaxrpc.SOAPClient;
054import com.sun.identity.saml.protocol.AssertionArtifact;
055
056import java.net.InetAddress;
057import java.net.URL;
058
059import java.rmi.RemoteException;
060import java.rmi.ServerException;
061
062import java.security.cert.X509Certificate;
063
064import java.util.Iterator;
065import java.util.ResourceBundle;
066
067import javax.xml.soap.SOAPException;
068
069
070/**
071 * The class <code>SecurityTokenManagerClient</code> is a <code>final</code> 
072 * class that provides interfaces to create, get and destroy
073 * <code>Assertion</code>s.
074 * <p>
075 * The class provides mechanisms to manage the <code>Assertion</code>s either
076 * locally (i.e., within the same JVM process) or remotely on another instance
077 * of OpenSSO. The default constructor will manage the <code>
078 * Assertion</code>s locally if it detects SAML web services running locally,
079 * else will use on of the configured OpenSSO. The constructor which
080 * accepts an <code>URL</code> will always use the URL to manage the assertions.
081 * <p>
082 * Having obtained an instance of <code>AssertionManagerClient</code>, its
083 * methods can be called to create/get <code>Assertion</code>, and 
084 * <code>AssertionArtifact</code>, and to obtain decision from an 
085 * <code>Query</code>.
086 *
087 * @supported.api
088 */
089public final class SecurityTokenManagerClient {
090
091    // Service name in naming
092    private static String SERVICE_NAME = "securitytokenmanager";
093
094    // Flag to determine if AssertionManager is local or remote
095    private static boolean checkedForLocal;
096    private static boolean isLocal;
097    private boolean useLocal;
098
099    // Remote JAX-RPC server for objects that use default constructor
100    private static SOAPClient remoteStub;
101
102    // If local pointer to SecurityTokenManager instance
103    private SecurityTokenManager securityTokenManager;
104    private String ssoToken = null;
105
106    // JAX-RPC remote stub
107    private SOAPClient stub;
108
109    static ResourceBundle bundle = 
110                Locale.getInstallResourceBundle("libLibertySecurity");
111    /**
112     * Returns an instance of <code>SecurityTokenManagerClient</code>
113     *
114     * @param credential credential of the caller used to see
115     *        if access to this security token manager client is allowed.
116     * @throws SecurityTokenException if unable to access the
117     *         the security token manager client.
118     */
119    public SecurityTokenManagerClient(Object credential)
120                                      throws SecurityTokenException {
121        if (!checkedForLocal) {
122            try {
123                // Construct the URL for local server.
124                remoteStub = getServiceEndPoint(
125                    SystemPropertiesManager.get(SAMLConstants.SERVER_PROTOCOL),
126                    SystemPropertiesManager.get(SAMLConstants.SERVER_HOST),
127                    SystemPropertiesManager.get(SAMLConstants.SERVER_PORT),
128                    SystemPropertiesManager.get(SAMLConstants.SERVER_URI));
129                remoteStub.send("checkForLocal", null, null, null);
130                if (SecurityTokenManagerImpl.isLocal) {
131                    isLocal = true;
132                    SecurityTokenManager.debug.warning(
133                            "STMC(): Using local service");
134                    securityTokenManager = new SecurityTokenManager(credential);
135                }
136                checkedForLocal = true;
137            } catch (Exception e) {
138                checkedForLocal = true;
139                if (SecurityTokenManager.debug.warningEnabled()) {
140                    SecurityTokenManager.debug.warning(
141                            "SecurityTokenManagerClient()Exception", e);
142                }
143                throw (new SecurityTokenException(e.getMessage()));
144            }
145        }
146        if (isLocal) {
147            useLocal = true;
148        } else {
149            // Use the remoteStub if set
150            stub = remoteStub;
151            try {
152                ssoToken =
153                    SessionManager.getProvider().getSessionID(credential);
154                stub.send("initialization", ssoToken, null, ssoToken); 
155            } catch (Exception e) {
156                if (SecurityTokenManager.debug.warningEnabled()) {
157                    SecurityTokenManager.debug.warning(
158                            "SecurityTokenManagerClient()Exception", e);
159                }
160                throw (new SecurityTokenException(e.getMessage()));
161            }
162        }
163    }
164    
165    /**
166     * Returns an instance of <code>SecurityTokenManagerClient</code>
167     * that will use the provided <code>URL</code> for the management
168     * of security tokens.
169     *
170     * @param url the <code>SecurityTokenManagerClient</code> service URL that
171     *        will be used to get <code>BinarySecurityToken</code> and
172     *        <code>SAMLSecurityToken</code>.
173     * @param credential credential of the caller used to see
174     *        if access to this security token manager client is allowed.
175     * @throws SecurityTokenException if unable to access the
176     *         the security token manager client.
177     */
178    public SecurityTokenManagerClient(String url, Object credential)
179        throws SecurityTokenException {
180        try {
181            // Construct the JAX-RPC stub and set the URL endpoint
182            ssoToken = SessionManager.getProvider().getSessionID(credential);
183            String[] urls = {url};
184            stub = new SOAPClient(urls);
185            stub.send("initialization", ssoToken, null, ssoToken);
186            useLocal = false;
187        } catch (Exception e) {
188            if (SecurityTokenManager.debug.warningEnabled()) {
189                SecurityTokenManager.debug.warning("STMC() Exception", e);
190            }
191            throw (new SecurityTokenException(e.getMessage()));
192        }
193    }
194
195    // Private method to get the service endpoint URL
196    private static SOAPClient getServiceEndPoint(String protocol,
197        String hostname, String port, String uri) throws Exception {
198        // Obtain the URL for the service endpoint
199        int intPort = Integer.parseInt(port);
200        URL weburl = SystemConfigurationUtil.getServiceURL(SERVICE_NAME,
201            protocol, hostname, intPort, uri);
202        String iurl = weburl.toString();
203        if (SecurityTokenManager.debug.messageEnabled()) {
204            SecurityTokenManager.debug.message(
205                "SecurityTokenManagerClient with URL: " + iurl);
206        }
207        String[] urls = {iurl};
208        return new SOAPClient(urls);
209    }
210
211    private static SOAPClient getRemoteStub()
212        throws SecurityTokenException {
213        boolean foundServer = false;
214        Exception ee = null;
215        SOAPClient remoteStub = null;
216        try {
217            // Get the list of platform servers
218            Iterator serverList =
219                SystemConfigurationUtil.getServerList().iterator();
220
221            // Get a server that is responding
222            while (serverList.hasNext() && !foundServer) {
223                URL u = new URL((String) serverList.next());
224                remoteStub = getServiceEndPoint(u.getProtocol(), u.getHost(),
225                    Integer.toString(u.getPort()), u.getPath());
226                // Check if the server is active
227                try {
228                    // this call will throw an exception if server is down
229                    remoteStub.send("checkForLocal", null, null, null);
230                    if (SecurityTokenManager.debug.messageEnabled()) {
231                        SecurityTokenManager.debug.message(
232                            "STMC(): Using the remote URL: " + u.toString());
233                    }
234                    foundServer = true;
235                    if (SecurityTokenManager.debug.warningEnabled()) {
236                        SecurityTokenManager.debug.warning(
237                            "STMC:getRemoteStub: remote server being used: "
238                            + u.toString());
239                    }
240                } catch (Exception e) {
241                    ee = e;
242                    if (SecurityTokenManager.debug.warningEnabled()) {
243                        SecurityTokenManager.debug.warning(
244                            "STMC:getRemoteStub: server (" +
245                            u.toString() + ") error: ", e);
246                    }
247                }
248            }
249        } catch (Exception f) {
250            ee = f;
251            if (SecurityTokenManager.debug.warningEnabled()) {
252                SecurityTokenManager.debug.warning(
253                        "STMC:getRemoteStub: generic error: ", f);
254            }
255        }
256        
257        if (!foundServer) {
258            // No valid server found. Return the last exception
259            if (ee != null) {
260                throw (new SecurityTokenException(ee.getMessage()));
261            } else {
262                throw (new SecurityTokenException(
263                    bundle.getString("serverNotFound")));
264            }
265        }
266        return (remoteStub);
267    }
268
269    /**
270     * Sets the alias of the certificate used for issuing <code>WSS</code>
271     * token, i.e. <code>WSS</code> <code>X509</code> Token, <code>WSS</code>
272     * SAML Token. If the <code>certAlias</code> is never set, a default
273     * certificate will be used for issuing <code>WSS</code> tokens.
274     *
275     * @param certAlias String alias name for the certificate.
276     * @throws SecurityTokenException if certificate for the
277     *            <code>certAlias</code> could not be found in key store.
278     * 
279     * @supported.api
280     */
281    public void setCertAlias(java.lang.String certAlias)
282        throws SecurityTokenException {
283        if (useLocal) {
284            securityTokenManager.setCertAlias(certAlias);
285        } else {
286            try {
287                Object[] obj = {certAlias, Boolean.TRUE};
288                stub.send("setCertificate", obj, null, ssoToken);
289            } catch (Exception e) {
290                if (SecurityTokenManager.debug.warningEnabled()) {
291                    SecurityTokenManager.debug.warning(
292                        "STMC:setCertAlias()", e);
293                }
294                throw (new SecurityTokenException(e.getMessage()));
295            }
296        }
297    }
298
299    /**
300     * Sets the  certificate used for issuing <code>WSS</code> token, i.e.
301     * <code>WSS</code> <code>X509</code> Token, <code>WSS</code> SAML Token.
302     * If the certificate is never set, a default certificate will
303     * be used for issuing <code>WSS</code> tokens
304     *
305     * @param cert <code>X509</code> certificate
306     * @throws SecurityTokenException if could not set Certificate.
307     */
308    public void setCertificate(X509Certificate cert)
309        throws SecurityTokenException {
310        if (useLocal) {
311            securityTokenManager.setCertificate(cert);
312        } else {
313            try {
314                String certString = Base64.encode(cert.getEncoded());
315                Object[] obj = {certString, Boolean.FALSE};
316                stub.send("setCertificate", obj, null, ssoToken);
317            } catch (Exception e) {
318                if (SecurityTokenManager.debug.warningEnabled()) {
319                    SecurityTokenManager.debug.warning(
320                        "STMC:setCertificate()", e);
321                }
322                throw (new SecurityTokenException(e.getMessage()));
323            }
324        }
325    }
326
327    /**
328     * Gets the <code>X509</code> certificate Token.
329     *
330     * @return <code>X509</code> certificate Token.
331     * @throws SecurityTokenException if the binary security token could
332     * not be obtained.
333     */
334    public BinarySecurityToken getX509CertificateToken()
335                                      throws SecurityTokenException {
336        if (useLocal) {
337            return securityTokenManager.getX509CertificateToken();
338        } 
339
340        String bst = null;
341        try {
342            bst = (String) stub.send("getX509CertificateToken", null, null,
343                ssoToken);
344            return (new BinarySecurityToken(XMLUtils.toDOMDocument(bst,
345                    SecurityTokenManager.debug).getDocumentElement()));
346        } catch (Exception e) {
347            if (SecurityTokenManager.debug.warningEnabled()) {
348                SecurityTokenManager.debug.warning(
349                    "STMC:getX509CertificateToken()", e);
350            }
351            throw (new SecurityTokenException(e.getMessage()));
352        }
353    }
354
355    /**
356     * Creates a SAML Assertion for message authentication.
357     *
358     * @param senderIdentity name identifier of the sender.
359     * @return Assertion which contains an <code>AuthenticationStatement</code>.
360     * @throws SecurityTokenException if the assertion could not be obtained.
361     * @throws SAMLException if unable to generate the SAML Assertion. 
362     */
363    public SecurityAssertion getSAMLAuthenticationToken(
364            NameIdentifier senderIdentity)
365            throws SecurityTokenException, SAMLException {
366        if (useLocal) {
367            return (securityTokenManager.getSAMLAuthenticationToken(
368                        senderIdentity));
369        }
370
371        try {
372            String ni = senderIdentity.toString(true, true);
373            String assertion = (String) stub.send("getSAMLAuthenticationToken", 
374                ni, null, ssoToken);
375            return (new SecurityAssertion(XMLUtils.toDOMDocument(assertion,
376                    SecurityTokenManager.debug).getDocumentElement()));
377        } catch (Exception re) {
378            if (SecurityTokenManager.debug.warningEnabled()) {
379                SecurityTokenManager.debug.warning(
380                    "STMC:getSAMLAuthenticationToken()", re);
381            }
382            throw (new SAMLException(re.getMessage()));
383        }
384    }
385
386    /**
387     * Creates a SAML Assertion for message authorization, the assertion could
388     * optionally contain an <code>AuthenticationStatement</code> which will be
389     * used for message authentication.
390     *
391     * @param senderIdentity name identifier of the sender.
392     * @param invocatorSession <code>SessionContext</code> of  the invocation 
393     *        identity, it is normally obtained by the credential reference in 
394     *        the SAML <code>AttributeDesignator</code> for discovery resource 
395     *        offering which is part of the liberty <code>ID-FF</code> 
396     *        <code>AuthenResponse</code>.
397     * @param resourceID id for the resource to be accessed.
398     * @param includeAuthN if true, include an 
399     *        <code>AutheticationStatement</code> in the Assertion which will be 
400     *        used for message authentication. 
401     * @param includeResourceAccessStatement if true, a 
402     *        <code>ResourceAccessStatement</code>
403     *        will be included in the Assertion 
404     *        (for <code>AuthorizeRequester</code> directive). If false, 
405     *        a <code>SessionContextStatement</code> will be included in the 
406     *        Assertion (for <code>AuthenticationSessionContext</code> 
407     *        directive). In the case when both <code>AuthorizeRequester</code> 
408     *        and <code>AuthenticationSessionContext</code> directive need to be
409     *        handled, use "true" as parameter here since the 
410     *        <code>SessionContext</code> will always be included in the 
411     *        <code>ResourceAccessStatement</code>.
412     * @param recipientProviderID recipient's provider ID.
413     * @return the <code>SecurityAssertion</code> object.
414     * @throws SecurityTokenException if the assertion could not be obtained.
415     * @throws SAMLException if unable to generate the SAML Assertion.
416     */
417    public SecurityAssertion getSAMLAuthorizationToken(
418            NameIdentifier senderIdentity,
419            SessionContext invocatorSession,
420            String resourceID,
421            boolean includeAuthN,
422            boolean includeResourceAccessStatement,
423            String recipientProviderID)
424            throws SecurityTokenException, SAMLException {
425        if (useLocal) {
426            return (securityTokenManager.getSAMLAuthorizationToken(
427                        senderIdentity, invocatorSession, resourceID,
428                        includeAuthN, includeResourceAccessStatement,
429                        recipientProviderID));
430        }
431
432        try {
433            String ni = senderIdentity.toString(true, true);
434            String sc = invocatorSession.toXMLString(true, true);
435            Object[] obj = {ni, sc, resourceID, Boolean.FALSE, 
436                Boolean.valueOf(includeAuthN),
437                Boolean.valueOf(includeResourceAccessStatement),
438                recipientProviderID};
439            String assertion = (String) stub.send("getSAMLAuthorizationToken",
440                obj, null, ssoToken);
441            return (new SecurityAssertion(XMLUtils.toDOMDocument(assertion,
442                    SecurityTokenManager.debug).getDocumentElement()));
443        } catch (Exception e) {
444            if (SecurityTokenManager.debug.warningEnabled()) {
445                SecurityTokenManager.debug.warning(
446                        "STMC:createAssertionArtifact:", e);
447            }
448            throw (new SecurityTokenException(e.getMessage()));
449        }
450    }
451
452    /**
453     * Creates a SAML Assertion for message authorization, the assertion could
454     * optionally contain an <code>AuthenticationStatement</code> which will be
455     * used for message authentication.
456     *
457     * @param senderIdentity name identifier of the sender.
458     * @param invocatorSession <code>SessionContext</code> of  the invocation 
459     *        identity, it is normally obtained by the credential reference in
460     *        the SAML <code>AttributeDesignator</code> for discovery resource   
461     *        offering which is part of the liberty <code>ID-FF</code> 
462     *        <code>AuthenResponse</code>.
463     * @param encResourceID Encrypted ID for the resource to be accessed.
464     * @param includeAuthN if true, include an 
465     *        <code>AutheticationStatement</code> in the
466     *        Assertion which will be used for message authentication. 
467     * @param includeResourceAccessStatement if true, 
468     *        a <code>ResourceAccessStatement</code> will be included in the 
469     *        Assertion (for <code>AuthorizeRequester</code> directive). If
470     *        false, a <code>SessionContextStatement</code> will be included in 
471     *        the Assertion (for <code>AuthenticationSessionContext</code> 
472     *        directive). In the case when both <code>AuthorizeRequester</code> 
473     *        and <code>AuthenticationSessionContext</code> directive need to be
474     *        handled, use "true" as parameter here since the 
475     *        <code>SessionContext</code> will always be included in the 
476     *        <code>ResourceAccessStatement</code>.
477     * @param recipientProviderID recipient's provider ID.
478     * @return the <code>SecurityAssertion</code> object.
479     * @throws SecurityTokenException if the assertion could not be obtained.
480     * @throws SAMLException if unable to generate the SAML Assertion.
481     */
482    public SecurityAssertion getSAMLAuthorizationToken(
483                NameIdentifier senderIdentity,
484                SessionContext invocatorSession,
485                EncryptedResourceID encResourceID,
486                boolean includeAuthN,
487                boolean includeResourceAccessStatement,
488                String recipientProviderID)
489        throws SecurityTokenException, SAMLException {
490        if (useLocal) {
491            return (securityTokenManager.getSAMLAuthorizationToken(
492                senderIdentity, invocatorSession, encResourceID,
493                includeAuthN, includeResourceAccessStatement,
494                recipientProviderID));
495        }
496
497        String assertion = null;
498
499        try {
500            String ni = senderIdentity.toString(true, true);
501            String sc = invocatorSession.toXMLString(true, true);
502            String resourceID = encResourceID.toString();
503            Object[] obj = {ni, sc, resourceID,  Boolean.TRUE,
504                Boolean.valueOf(includeAuthN),
505                Boolean.valueOf(includeResourceAccessStatement),
506                recipientProviderID};
507            assertion = (String) stub.send("getSAMLAuthorizationToken",
508                obj, null, ssoToken);
509            return (new SecurityAssertion(XMLUtils.toDOMDocument(assertion,
510                    SecurityTokenManager.debug).getDocumentElement()));
511        } catch (Exception e) {
512            if (SecurityTokenManager.debug.warningEnabled()) {
513                SecurityTokenManager.debug.warning(
514                        "STMC:getSAMLAuthorizationToken() ", e);
515            }
516            throw (new SecurityTokenException(e.getMessage()));
517        }
518    }
519}




























































Copyright © 2010-2017, ForgeRock All Rights Reserved.