/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License"). You
* may not use this file except in compliance with the License. You can obtain
* a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
* or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
* Sun designates this particular file as subject to the "Classpath" exception
* as provided by Sun in the GPL Version 2 section of the License file that
* accompanied this code. If applicable, add the following below the License
* Header, with the fields enclosed by brackets [] replaced by your own
* identifying information: "Portions Copyrighted [year]
* [name of copyright owner]"
*
* Contributor(s):
*
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license." If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above. However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/
package com.sun.xml.ws.security.secconv;
import com.sun.xml.ws.api.security.trust.WSTrustException;
import com.sun.xml.ws.policy.AssertionSet;
import com.sun.xml.ws.policy.NestedPolicy;
import com.sun.xml.ws.policy.PolicyAssertion;
import com.sun.xml.ws.policy.impl.bindings.AppliesTo;
import com.sun.xml.ws.runtime.util.Session;
import com.sun.xml.ws.runtime.util.SessionManager;
import com.sun.xml.ws.security.IssuedTokenContext;
import com.sun.xml.ws.security.SecurityContextToken;
import com.sun.xml.ws.security.SecurityContextTokenInfo;
import com.sun.xml.ws.security.Token;
import com.sun.xml.ws.security.impl.policy.PolicyUtil;
import com.sun.xml.ws.security.impl.policy.Trust10;
import com.sun.xml.ws.security.policy.AlgorithmSuite;
import com.sun.xml.ws.security.policy.Constants;
import com.sun.xml.ws.security.policy.SymmetricBinding;
import com.sun.xml.ws.security.trust.impl.bindings.ObjectFactory;
import com.sun.xml.ws.security.trust.Configuration;
import com.sun.xml.ws.security.trust.WSTrustConstants;
import com.sun.xml.ws.security.trust.elements.BinarySecret;
import com.sun.xml.ws.security.trust.elements.CancelTarget;
import com.sun.xml.ws.security.trust.elements.Entropy;
import com.sun.xml.ws.security.trust.elements.Lifetime;
import com.sun.xml.ws.security.trust.elements.RequestedAttachedReference;
import com.sun.xml.ws.security.trust.elements.RequestedUnattachedReference;
import com.sun.xml.ws.security.trust.elements.RequestedProofToken;
import com.sun.xml.ws.security.trust.elements.RequestedSecurityToken;
import com.sun.xml.ws.security.trust.elements.RequestSecurityToken;
import com.sun.xml.ws.security.trust.elements.RequestSecurityTokenResponse;
import com.sun.xml.ws.security.trust.elements.RequestSecurityTokenResponseCollection;
import com.sun.xml.ws.security.trust.elements.str.Reference;
import com.sun.xml.ws.security.trust.elements.str.DirectReference;
import com.sun.xml.ws.security.trust.elements.str.SecurityTokenReference;
import com.sun.xml.ws.security.trust.impl.bindings.RequestSecurityTokenResponseType;
import com.sun.xml.ws.security.trust.util.WSTrustUtil;
import com.sun.xml.ws.security.wsu10.AttributedDateTime;
import com.sun.xml.ws.security.policy.SecureConversationToken;
import com.sun.xml.ws.security.secconv.impl.SecurityContextTokenInfoImpl;
import com.sun.xml.wss.impl.misc.SecurityUtil;
import java.net.URI;
import java.net.URISyntaxException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.sun.xml.ws.security.secconv.logging.LogDomainConstants;
import com.sun.xml.ws.security.secconv.logging.LogStringsMessages;
import javax.xml.bind.JAXBElement;
public class WSSCContract {
private static final Logger log =
Logger.getLogger(
LogDomainConstants.WSSC_IMPL_DOMAIN,
LogDomainConstants.WSSC_IMPL_DOMAIN_BUNDLE);
//private Configuration config;
private long currentTime;
private static WSSCElementFactory eleFac = WSSCElementFactory.newInstance();
private static final int DEFAULT_KEY_SIZE = 128;
// ToDo: Should read from the configuration
private static final long TIMEOUT = 36000000;
private static final SimpleDateFormat calendarFormatter
= new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'.'sss'Z'",Locale.getDefault());
public WSSCContract(){
//Empty default constructor
}
public WSSCContract(Configuration config){
init(config);
}
public final void init(final Configuration config){
//this.config = config;
}
/** Issue a SecurityContextToken */
public RequestSecurityTokenResponse issue(
final RequestSecurityToken request, final IssuedTokenContext context, final SecureConversationToken scToken) throws WSSecureConversationException {
// TokenType and context
URI tokenType = null;
URI con = null;
URI computeKeyAlgo = null;
tokenType = URI.create(WSSCConstants.SECURITY_CONTEXT_TOKEN_TYPE);
final String conStr = request.getContext();
if (conStr != null) {
try {
con = new URI(conStr);
} catch (URISyntaxException ex){
log.log(Level.SEVERE,
LogStringsMessages.WSSC_0008_URISYNTAX_EXCEPTION(request.getContext()), ex);
throw new WSSecureConversationException(LogStringsMessages.WSSC_0008_URISYNTAX_EXCEPTION(request.getContext()), ex);
}
}
computeKeyAlgo = URI.create(WSTrustConstants.CK_PSHA1);
// AppliesTo
final AppliesTo scopes = request.getAppliesTo();
final RequestedProofToken proofToken = eleFac.createRequestedProofToken();
// Get client entropy
byte[] clientEntr = null;
final Entropy clientEntropy = request.getEntropy();
if (clientEntropy != null){
final BinarySecret clientBS = clientEntropy.getBinarySecret();
if (clientBS == null){
//ToDo
if (log.isLoggable(Level.FINE)) {
log.log(Level.FINE,
LogStringsMessages.WSSC_0009_CLIENT_ENTROPY_VALUE("null"));
}
}else {
clientEntr = clientBS.getRawValue();
if (log.isLoggable(Level.FINE)) {
log.log(Level.FINE,
LogStringsMessages.WSSC_0009_CLIENT_ENTROPY_VALUE(clientEntropy.toString()));
}
}
}
final RequestSecurityTokenResponse response = createRSTR(computeKeyAlgo, scToken, request, scopes, clientEntr, proofToken, tokenType, clientEntropy, context, con);
if (log.isLoggable(Level.FINE)) {
log.log(Level.FINE,
LogStringsMessages.WSSC_0014_RSTR_RESPONSE(elemToString(response)));
}
return response;
}
private RequestSecurityTokenResponse createRSTR(final URI computeKeyAlgo, final SecureConversationToken scToken, final RequestSecurityToken request, final AppliesTo scopes, final byte[] clientEntr, final RequestedProofToken proofToken, final URI tokenType, final Entropy clientEntropy, final IssuedTokenContext context, final URI con) throws WSSecureConversationException, WSSecureConversationException {
Trust10 trust10 = null;
SymmetricBinding symBinding = null;
final NestedPolicy wsPolicy = scToken.getBootstrapPolicy();
final AssertionSet assertionSet = wsPolicy.getAssertionSet();
for(PolicyAssertion policyAssertion : assertionSet){
if(PolicyUtil.isTrust10(policyAssertion)){
trust10 = (Trust10)policyAssertion;
}else if(PolicyUtil.isSymmetricBinding(policyAssertion)){
symBinding = (SymmetricBinding)policyAssertion;
}
}
boolean reqServerEntr = true;
boolean reqClientEntr=false;
if(trust10 != null){
final Set trustReqdProps = trust10.getRequiredProperties();
reqServerEntr = trustReqdProps.contains(Constants.REQUIRE_SERVER_ENTROPY);
reqClientEntr = trustReqdProps.contains(Constants.REQUIRE_CLIENT_ENTROPY);
if(clientEntropy == null){
if(reqClientEntr){
log.log(Level.SEVERE,
LogStringsMessages.WSSC_0010_CLIENT_ENTROPY_CANNOT_NULL());
throw new WSSecureConversationException(LogStringsMessages.WSSC_0010_CLIENT_ENTROPY_CANNOT_NULL());
}else{
reqServerEntr = true;
}
}
}
int keySize = (int)request.getKeySize();
if (keySize < 1 && symBinding!=null ){
final AlgorithmSuite algoSuite = symBinding.getAlgorithmSuite();
keySize = algoSuite.getMinSKLAlgorithm();
}
if (keySize < 1){
keySize = DEFAULT_KEY_SIZE;
}
if (log.isLoggable(Level.FINE)) {
log.log(Level.FINE,
LogStringsMessages.WSSC_0011_KEY_SIZE_VALUE(keySize, this.DEFAULT_KEY_SIZE));
}
byte[] secret = WSTrustUtil.generateRandomSecret(keySize/8);
final String proofTokenType = (clientEntr == null ||clientEntr.length ==0)
? BinarySecret.SYMMETRIC_KEY_TYPE :BinarySecret.NONCE_KEY_TYPE;
Entropy serverEntropy = null;
if(reqServerEntr){
final BinarySecret serverBS = eleFac.createBinarySecret(secret, proofTokenType);
if (proofTokenType.equals(BinarySecret.NONCE_KEY_TYPE)){
serverEntropy = eleFac.createEntropy(serverBS);
proofToken.setProofTokenType(RequestedProofToken.COMPUTED_KEY_TYPE);
proofToken.setComputedKey(computeKeyAlgo);
// compute the secret key
try {
secret = SecurityUtil.P_SHA1(clientEntr, secret, keySize/8);
} catch (Exception ex){
log.log(Level.SEVERE,
LogStringsMessages.WSSC_0012_COMPUTE_SECKEY(), ex);
throw new WSSecureConversationException(LogStringsMessages.WSSC_0012_COMPUTE_SECKEY(), ex);
}
} else {
proofToken.setProofTokenType(RequestedProofToken.BINARY_SECRET_TYPE);
proofToken.setBinarySecret(serverBS);
}
}else if (clientEntropy != null){
secret = clientEntr;
proofToken.setProofTokenType(RequestedProofToken.BINARY_SECRET_TYPE);
proofToken.setBinarySecret(clientEntropy.getBinarySecret());
}
return createResponse(serverEntropy, con, scopes, secret, proofToken, context, tokenType);
}
private RequestSecurityTokenResponse createResponse(final Entropy serverEntropy, final URI con, final AppliesTo scopes, final byte[] secret, final RequestedProofToken proofToken, final IssuedTokenContext context, final URI tokenType) throws WSSecureConversationException {
// Create Security Context and SecurityContextToken
final SecurityContextToken token = WSTrustUtil.createSecurityContextToken(eleFac);
final RequestedSecurityToken rst = eleFac.createRequestedSecurityToken(token);
// Create references
final SecurityTokenReference attachedReference = createSecurityTokenReference(token.getWsuId(),false);
final RequestedAttachedReference rar = eleFac.createRequestedAttachedReference(attachedReference);
final SecurityTokenReference unattachedRef = createSecurityTokenReference(token.getIdentifier().toString(), true);
final RequestedUnattachedReference rur = eleFac.createRequestedUnattachedReference(unattachedRef);
// Create Lifetime
final Lifetime lifetime = createLifetime();
RequestSecurityTokenResponse response = null;
try {
response =
eleFac.createRSTRForIssue(tokenType, con, rst, scopes, rar, rur, proofToken, serverEntropy, lifetime);
} catch (WSTrustException ex){
log.log(Level.SEVERE,
LogStringsMessages.WSSC_0020_PROBLEM_CREATING_RSTR(), ex);
throw new WSSecureConversationException(LogStringsMessages.WSSC_0020_PROBLEM_CREATING_RSTR(), ex);
}
final Session session =
SessionManager.getSessionManager().createSession(token.getIdentifier().toString());
if (log.isLoggable(Level.FINE)) {
log.log(Level.FINE,
LogStringsMessages.WSSC_1010_CREATING_SESSION(token.getIdentifier()));
}
populateITC(session, secret, token, attachedReference, context, unattachedRef);
return response;
}
private void populateITC(final Session session, final byte[] secret, final SecurityContextToken token, final SecurityTokenReference attachedReference, final IssuedTokenContext context, final SecurityTokenReference unattachedRef) {
// Populate the IssuedTokenContext
context.setSecurityToken(token);
context.setAttachedSecurityTokenReference(attachedReference);
context.setUnAttachedSecurityTokenReference(unattachedRef);
context.setProofKey(secret);
context.setCreationTime(new Date(currentTime));
context.setExpirationTime(new Date(currentTime + TIMEOUT));
final SecurityContextTokenInfo sctinfo =
new SecurityContextTokenInfoImpl();
sctinfo.setIdentifier(token.getIdentifier().toString());
sctinfo.setExternalId(token.getWsuId());
sctinfo.addInstance(null, secret);
sctinfo.setCreationTime(new Date(currentTime));
sctinfo.setExpirationTime(new Date(currentTime + TIMEOUT));
session.setSecurityInfo(sctinfo);
}
/** Issue a Collection of Token(s) possibly for different scopes */
public RequestSecurityTokenResponseCollection issueMultiple(
final RequestSecurityToken request, final IssuedTokenContext context)throws WSSecureConversationException {
return null;
}
/** Renew a SecurityContextToken */
public RequestSecurityTokenResponse renew(
final RequestSecurityToken request, final IssuedTokenContext context)
throws WSSecureConversationException {
return null;
}
/** Cancel a SecurityContextToken */
public RequestSecurityTokenResponse cancel(
final RequestSecurityToken request, final IssuedTokenContext context, final Map issuedTokCtxMap)
throws WSSecureConversationException {
final CancelTarget cancelTgt = request.getCancelTarget();
final SecurityTokenReference str = cancelTgt.getSecurityTokenReference();
String id = null;
final Reference ref = str.getReference();
if (ref.getType().equals("Reference")){
id = ((DirectReference)ref).getURIAttr().toString();
}
final IssuedTokenContext cxt = (IssuedTokenContext)issuedTokCtxMap.get(id);
if (cxt == null || cxt.getSecurityToken() == null){
log.log(Level.SEVERE,
LogStringsMessages.WSSC_0015_UNKNOWN_CONTEXT(id));
throw new WSSecureConversationException(LogStringsMessages.WSSC_0015_UNKNOWN_CONTEXT(id));
}
final RequestSecurityTokenResponse rstr = eleFac.createRSTRForCancel();
if (log.isLoggable(Level.FINE)) {
log.log(Level.FINE,
LogStringsMessages.WSSC_0014_RSTR_RESPONSE(elemToString(rstr)));
}
return rstr;
}
/** Validate a SecurityContextToken */
public RequestSecurityTokenResponse validate(
final RequestSecurityToken request, final IssuedTokenContext context)
throws WSSecureConversationException {
return null;
}
/**
* handle an unsolicited RSTR like in the case of
* Client Initiated Secure Conversation.
*/
public void handleUnsolicited(
final RequestSecurityTokenResponse rstr, final IssuedTokenContext context)
throws WSSecureConversationException {
//final AppliesTo scope = rstr.getAppliesTo();
final RequestedSecurityToken rqSecToken = rstr.getRequestedSecurityToken();
final Token token = rqSecToken.getToken();
final RequestedProofToken rqProofToken = rstr.getRequestedProofToken();
final String proofTokenType = rqProofToken.getProofTokenType();
if(proofTokenType.equals(RequestedProofToken.BINARY_SECRET_TYPE)){
final BinarySecret binarySecret = rqProofToken.getBinarySecret();
if(binarySecret.getType().equals(BinarySecret.SYMMETRIC_KEY_TYPE)){
final byte [] secret = binarySecret.getRawValue();
context.setProofKey(secret);
}
}else if(proofTokenType.equals(RequestedProofToken.ENCRYPTED_KEY_TYPE)){
//ToDo
}
context.setSecurityToken(token);
final long curTime = System.currentTimeMillis();
final Date creationTime = new Date(curTime);
final Date expirationTime = new Date(curTime + TIMEOUT);
context.setCreationTime(creationTime);
context.setExpirationTime(expirationTime);
if (log.isLoggable(Level.FINER)) {
log.log(Level.FINER,
LogStringsMessages.WSSC_1003_SETTING_TIMES(creationTime.toString(), expirationTime.toString()));
}
}
private SecurityTokenReference createSecurityTokenReference(final String id, final boolean unattached){
final String uri = (unattached?id:"#"+id);
final Reference ref = eleFac.createDirectReference(WSSCConstants.SECURITY_CONTEXT_TOKEN_TYPE, uri);
return eleFac.createSecurityTokenReference(ref);
}
private Lifetime createLifetime() {
final Calendar cal = new GregorianCalendar();
int offset = cal.get(Calendar.ZONE_OFFSET);
if (cal.getTimeZone().inDaylightTime(cal.getTime())) {
offset += cal.getTimeZone().getDSTSavings();
}
synchronized (calendarFormatter) {
calendarFormatter.setTimeZone(cal.getTimeZone());
// always send UTC/GMT time
final long beforeTime = cal.getTimeInMillis();
currentTime = beforeTime - offset;
cal.setTimeInMillis(currentTime);
final AttributedDateTime created = new AttributedDateTime();
created.setValue(calendarFormatter.format(cal.getTime()));
final AttributedDateTime expires = new AttributedDateTime();
cal.setTimeInMillis(currentTime + TIMEOUT);
expires.setValue(calendarFormatter.format(cal.getTime()));
final Lifetime lifetime = eleFac.createLifetime(created, expires);
return lifetime;
}
}
private String elemToString(final RequestSecurityTokenResponse rstr){
try {
final javax.xml.bind.Marshaller marshaller = eleFac.getContext().createMarshaller();
final JAXBElement<RequestSecurityTokenResponseType> rstrElement = (new ObjectFactory()).createRequestSecurityTokenResponse((RequestSecurityTokenResponseType)rstr);
marshaller.setProperty(javax.xml.bind.Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
final java.io.StringWriter writer = new java.io.StringWriter();
marshaller.marshal(rstrElement, writer);
return writer.toString();
} catch (Exception e) {
log.log(Level.SEVERE,
LogStringsMessages.WSSC_0001_ERROR_MARSHAL_LOG());
throw new RuntimeException(LogStringsMessages.WSSC_0001_ERROR_MARSHAL_LOG(), e);
}
}
}
|