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.