com.sun.xml.wss.impl.WssProviderSecurityEnvironment Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of webservices-rt Show documentation
Show all versions of webservices-rt Show documentation
This module contains the Metro runtime code.
/*
* Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Distribution License v. 1.0, which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/*
* $Id: WssProviderSecurityEnvironment.java,v 1.2 2010-10-21 15:37:15 snajper Exp $
*/
package com.sun.xml.wss.impl;
import com.sun.xml.ws.security.impl.kerberos.KerberosContext;
import java.math.BigInteger;
import java.security.AccessController;
import java.security.Key;
import java.security.KeyStore;
import java.security.PublicKey;
import java.security.Principal;
import java.security.PrivateKey;
import java.security.KeyStoreException;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.security.cert.CertPathBuilder;
import java.security.cert.X509CertSelector;
import java.security.cert.PKIXBuilderParameters;
import java.security.cert.CertificateExpiredException;
import java.security.cert.CertificateNotYetValidException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Map;
import java.util.Set;
import java.util.Date;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Iterator;
import java.util.Enumeration;
import java.util.StringTokenizer;
import java.util.GregorianCalendar;
import javax.security.auth.Subject;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.x500.X500Principal;
import javax.security.auth.x500.X500PrivateCredential;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
import javax.crypto.SecretKey;
import org.apache.xml.security.utils.Base64;
import org.apache.xml.security.exceptions.Base64DecodingException;
import com.sun.xml.ws.api.server.WSEndpoint;
import com.sun.xml.wss.NonceManager;
import com.sun.xml.wss.SecurityEnvironment;
import com.sun.xml.wss.XWSSecurityException;
import com.sun.xml.wss.core.Timestamp;
import com.sun.xml.wss.core.reference.KeyIdentifierSPI;
import com.sun.xml.wss.impl.misc.DefaultSecurityEnvironmentImpl;
import com.sun.xml.wss.core.reference.X509SubjectKeyIdentifier;
import com.sun.xml.wss.impl.callback.CertificateValidationCallback;
import com.sun.xml.wss.saml.Assertion;
//import com.sun.xml.wss.saml.assertion.AuthorityBinding;
import com.sun.xml.wss.impl.policy.mls.AuthenticationTokenPolicy;
import com.sun.xml.wss.impl.configuration.DynamicApplicationContext;
import java.io.IOException;
import javax.xml.stream.XMLStreamReader;
import org.ietf.jgss.GSSName;
import org.w3c.dom.Element;
import org.w3c.dom.Document;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.PrivilegedAction;
import java.security.cert.CertPath;
import java.security.cert.CertPathValidator;
import java.security.cert.CertStore;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateFactory;
import java.security.cert.CollectionCertStoreParameters;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
//import javax.security.auth.message.callback.PasswordValidationCallback;
import javax.security.auth.callback.UnsupportedCallbackException;
import javax.security.auth.message.callback.CertStoreCallback;
import javax.security.auth.message.callback.PasswordValidationCallback;
import javax.security.auth.message.callback.PrivateKeyCallback;
import javax.security.auth.message.callback.SecretKeyCallback;
import javax.security.auth.message.callback.TrustStoreCallback;
import org.ietf.jgss.GSSCredential;
public class WssProviderSecurityEnvironment implements SecurityEnvironment {
/* menu of module options - includes algorithm Ids, keystore aliases etc., */
private Map _securityOptions;
/* Callbacks */
private CallbackHandler _handler;
/* Map of aliases-key passwords obtained via Module Options */
//Map aliases_keypwds = null;
// value of the maximum skew between the local times of two
// systems (in milliseconds).
// Keeping it 1 minute.
protected final long MAX_CLOCK_SKEW = 360000;
// milliseconds (set to 5 mins), time for which a timestamp is considered fresh
protected final long TIMESTAMP_FRESHNESS_LIMIT = 5 * 60 * 1000;
private static final SimpleDateFormat calendarFormatter1 =
new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
private static final SimpleDateFormat calendarFormatter2 =
new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'.'SSS'Z'");
public WssProviderSecurityEnvironment(CallbackHandler handler, Map options)
throws XWSSecurityException {
_handler = new PriviledgedHandler(handler);
_securityOptions = options;
if (_securityOptions != null) {
String mo_aliases = (String)_securityOptions.get("ALIASES");
String mo_keypwds = (String)_securityOptions.get("PASSWORDS");
if (mo_aliases != null && mo_keypwds != null) {
StringTokenizer aliases = new StringTokenizer(mo_aliases, " ");
StringTokenizer keypwds = new StringTokenizer(mo_keypwds, " ");
if (aliases.countTokens() != keypwds.countTokens())
;// log.INFO
// while (aliases.hasMoreElements()) {
// aliases_keypwds.put(aliases.nextToken(), keypwds.nextToken());
// }
}
}
}
/*
* @throws XWSSecurityException
*/
public PrivateKey getPrivateKey(Map context, String alias)
throws XWSSecurityException {
PrivateKey privateKey = null;
try {
PrivateKeyCallback.Request request =
new PrivateKeyCallback.AliasRequest(alias);
PrivateKeyCallback pkCallback = new PrivateKeyCallback(request);
Callback[] callbacks = new Callback[] { pkCallback };
_handler.handle(callbacks);
privateKey = (PrivateKey) pkCallback.getKey();
} catch (Exception e) {
throw new XWSSecurityException(e);
}
if (privateKey == null) {
throw new XWSSecurityException(
"Unable to locate private key for the alias " + alias);
}
return privateKey;
}
/*
* Retrieves the PrivateKey corresponding to the cert
* with the given KeyIdentifier value
*
* @param keyIdentifier an Opaque identifier indicating
* the X509 certificate
*
* @return the PrivateKey corresponding to the cert
* with the given KeyIdentifier value
*
* @throws XWSSecurityException
*/
public PrivateKey getPrivateKey(Map context, byte[] keyIdentifier)
throws XWSSecurityException {
/*
use PrivateKeyCallback
*/
try {
Subject subject = getSubject(context);
if (subject != null) {
Set set = subject.getPrivateCredentials(X500PrivateCredential.class);
if (set != null) {
Iterator it = set.iterator();
while (it.hasNext()) {
X500PrivateCredential cred = (X500PrivateCredential)it.next();
if (matchesKeyIdentifier(Base64.decode(keyIdentifier),
cred.getCertificate()))
return cred.getPrivateKey();
}
}
}
PrivateKeyCallback.Request request = new PrivateKeyCallback.SubjectKeyIDRequest(
keyIdentifier);
PrivateKeyCallback pkCallback = new PrivateKeyCallback(request);
Callback[] callbacks = new Callback[] { pkCallback };
_handler.handle(callbacks);
return pkCallback.getKey();
} catch (Exception e) {
throw new XWSSecurityException(e);
}
}
/*
* Retrieves the PrivateKey corresponding to the given cert
*
* @param cert an X509 certificate
*
* @return the PrivateKey corresponding to the cert
*
* @throws XWSSecurityException
*/
public PrivateKey getPrivateKey(Map context, X509Certificate cert)
throws XWSSecurityException {
/*
use PrivateKeyCallback
*/
try {
Subject subject = getSubject(context);
if (subject != null) {
Set set = subject.getPrivateCredentials(X500PrivateCredential.class);
if (set != null) {
String issuerName = org.apache.xml.security.utils.
RFC2253Parser.normalize(
cert.getIssuerDN().getName());
Iterator it = set.iterator();
while (it.hasNext()) {
X500PrivateCredential cred = (X500PrivateCredential)it.next();
X509Certificate x509Cert = cred.getCertificate();
BigInteger serialNo = x509Cert.getSerialNumber();
X500Principal currentIssuerPrincipal = x509Cert.getIssuerX500Principal();
X500Principal issuerPrincipal = new X500Principal(issuerName);
if (serialNo.equals(cert.getSerialNumber())
&& currentIssuerPrincipal.equals(issuerPrincipal)) {
return cred.getPrivateKey();
}
}
}
}
PrivateKeyCallback.Request request = new PrivateKeyCallback.IssuerSerialNumRequest(
cert.getIssuerX500Principal(), cert.getSerialNumber());
PrivateKeyCallback pkCallback = new PrivateKeyCallback(request);
Callback[] callbacks = new Callback[] { pkCallback };
_handler.handle(callbacks);
return pkCallback.getKey();
} catch (Exception e) {
throw new XWSSecurityException(e);
}
}
/*
* Retrieves the matching PrivateKey corresponding to cert whose
* SerialNumber and IssuerName are given
*
* @param serialNumber X509Certificate SerialNumber
* @param issuerName X509Certificate IssuerName
*
* @return PrivateKey
*
* @throws XWSSecurityException
*/
public PrivateKey getPrivateKey(Map context, BigInteger serialNumber, String issuerName)
throws XWSSecurityException {
/*
use PrivateKeyCallback
*/
try {
Subject subject = getSubject(context);
if (subject != null) {
Set set = subject.getPrivateCredentials(X500PrivateCredential.class);
if (set != null) {
Iterator it = set.iterator();
while (it.hasNext()) {
X500PrivateCredential cred = (X500PrivateCredential)it.next();
X509Certificate x509Cert = cred.getCertificate();
BigInteger serialNo = x509Cert.getSerialNumber();
X500Principal currentIssuerPrincipal = x509Cert.getIssuerX500Principal();
X500Principal issuerPrincipal = new X500Principal(issuerName);
if (serialNo.equals(serialNumber)
&& currentIssuerPrincipal.equals(issuerPrincipal)) {
return cred.getPrivateKey();
}
}
}
}
PrivateKeyCallback.Request request = new PrivateKeyCallback.IssuerSerialNumRequest(
new X500Principal(issuerName), serialNumber);
PrivateKeyCallback pkCallback = new PrivateKeyCallback(request);
Callback[] callbacks = new Callback[] { pkCallback };
_handler.handle(callbacks);
return pkCallback.getKey();
} catch (Exception e) {
throw new XWSSecurityException(e);
}
}
/**
* Retrieves a reasonable default value for the current user's
* X509Certificate if one exists.
*
* @return the default certificate for the current user
*
* @param context
* @throws XWSSecurityException
*/
public X509Certificate getDefaultCertificate(Map context)
throws XWSSecurityException {
/*
use PrivateKeyCallback to get the
certChain - return the first certificate
*/
Subject subject = getSubject(context);
if (subject != null) {
Set set = subject.getPublicCredentials(X509Certificate.class);
if (set != null && set.size() == 1)
return ((X509Certificate)(set.toArray())[0]);
}
PrivateKeyCallback pkCallback = new PrivateKeyCallback(null);
Callback[] _callbacks = new Callback[] { pkCallback };
try {
_handler.handle(_callbacks);
} catch (Exception e) {
throw new XWSSecurityException(e);
}
Certificate[] chain = pkCallback.getChain();
if (chain == null) {
throw new XWSSecurityException(
"Empty certificate chain returned by PrivateKeyCallback");
}
return (X509Certificate)chain[0];
}
/**
* Authenticate the user against a list of known username-password
* pairs.
*
* @param username
* @param password
* @return true if the username-password pair is valid
*/
public boolean authenticateUser(Map context,String username, String password)
throws XWSSecurityException {
/*
use PasswordValidationCallback
*/
char[] pwd = (password == null) ? null : password.toCharArray();
//PasswordValidationCallback pvCallback = new PasswordValidationCallback(username, pwd);
PasswordValidationCallback pvCallback = new PasswordValidationCallback(
this.getRequesterSubject(context),username, pwd);
Callback[] callbacks = new Callback[] { pvCallback };
try {
_handler.handle(callbacks);
} catch (Exception e) {
throw new XWSSecurityException(e);
}
// zero the password
if (pwd != null)
pvCallback.clearPassword();
return pvCallback.getResult();
}
public String authenticateUser(Map context, String username) throws XWSSecurityException {
throw new UnsupportedOperationException("Not supported yet.");
}
/**
* Authenticate the user given the password digest.
*
* @param username
* @param passwordDigest
* @param nonce
* @param created
* @return true if the password digest is valid
*/
public boolean authenticateUser(
Map context,
String username,
String passwordDigest,
String nonce,
String created)
throws XWSSecurityException {
/*
can not implement
*/
return false;
}
/**
* Validate an X509Certificate.
* @return true, if the cert is a valid one, false o/w.
* @throws XWSSecurityException
* if there is some problem during validation.
*/
public boolean validateCertificate(X509Certificate cert, Map context)
throws XWSSecurityException {
/*
use TrustStore and CertStore
*/
try {
cert.checkValidity();
} catch (CertificateExpiredException e) {
throw new XWSSecurityException("X509Certificate Expired", e);
} catch (CertificateNotYetValidException e) {
throw new XWSSecurityException("X509Certificate not yet valid", e);
}
// for self-signed certificate
if(cert.getIssuerX500Principal().equals(cert.getSubjectX500Principal())){
if(isTrustedSelfSigned(cert)){
return true;
}else{
throw new XWSSecurityException("Validation of self signed certificate failed");
}
}
X509CertSelector certSelector = new X509CertSelector();
certSelector.setCertificate(cert);
PKIXBuilderParameters parameters;
CertPathBuilder builder = null;
CertPathValidator certValidator = null;
CertPath certPath = null;
List certChainList = new ArrayList();
boolean caFound = false;
Principal certChainIssuer = null;
int noOfEntriesInTrustStore = 0;
boolean isIssuerCertMatched = false;
try {
Callback[] callbacks = null;
CertStoreCallback csCallback = null;
TrustStoreCallback tsCallback = null;
if (tsCallback == null && csCallback == null) {
csCallback = new CertStoreCallback();
tsCallback = new TrustStoreCallback();
callbacks = new Callback[] { csCallback, tsCallback };
} else if (csCallback == null) {
csCallback = new CertStoreCallback();
callbacks = new Callback[] { csCallback };
} else if (tsCallback == null) {
tsCallback = new TrustStoreCallback();
callbacks = new Callback[] { tsCallback };
}
try {
_handler.handle(callbacks);
} catch (Exception e) {
throw new XWSSecurityException(e);
}
parameters = new PKIXBuilderParameters(tsCallback.getTrustStore(), certSelector);
parameters.setRevocationEnabled(false);
if (KeyIdentifierSPI.isIBMVM) {
//requires the actual cert to be in a certstore
CertStore cs = CertStore.getInstance("Collection",
new CollectionCertStoreParameters(Collections.singleton(cert)));
parameters.addCertStore(cs);
} else {
parameters.addCertStore(csCallback.getCertStore());
}
Certificate[] certChain = null;
String certAlias = tsCallback.getTrustStore().getCertificateAlias(cert);
if(certAlias != null){
certChain = tsCallback.getTrustStore().getCertificateChain(certAlias);
}
if(certChain == null){
certChainList.add(cert);
certChainIssuer = cert.getIssuerX500Principal();
noOfEntriesInTrustStore = tsCallback.getTrustStore().size();
}else{
certChainList = Arrays.asList(certChain);
}
while(!caFound && noOfEntriesInTrustStore-- != 0 && certChain == null){
Enumeration aliases = tsCallback.getTrustStore().aliases();
while (aliases.hasMoreElements()) {
String alias = (String) aliases.nextElement();
Certificate certificate = tsCallback.getTrustStore().getCertificate(alias);
if (certificate == null || !"X.509".equals(certificate.getType()) || certChainList.contains(certificate)) {
continue;
}
X509Certificate x509Cert = (X509Certificate) certificate;
if(certChainIssuer.equals(x509Cert.getSubjectX500Principal())){
certChainList.add(certificate);
if(x509Cert.getSubjectX500Principal().equals(x509Cert.getIssuerX500Principal())){
caFound = true;
break;
}else{
certChainIssuer = x509Cert.getIssuerDN();
if(!isIssuerCertMatched){
isIssuerCertMatched = true;
}
}
}else{
continue;
}
}
if(!caFound){
if(!isIssuerCertMatched){
break;
}else{
isIssuerCertMatched = false;
}
}
}
try{
CertificateFactory cf = CertificateFactory.getInstance("X.509");
certPath = cf.generateCertPath(certChainList);
certValidator = CertPathValidator.getInstance("PKIX");
}catch(Exception e){
throw new CertificateValidationCallback.CertificateValidationException(e.getMessage(), e);
}
} catch (Exception e) {
// Log Message
throw new XWSSecurityException(e);
}
try {
certValidator.validate(certPath, parameters);
} catch (Exception e) {
// log message
return false;
}
return true;
}
private boolean isTrustedSelfSigned(X509Certificate cert) throws XWSSecurityException {
try {
Callback[] callbacks = null;
CertStoreCallback csCallback = null;
TrustStoreCallback tsCallback = null;
if (tsCallback == null && csCallback == null) {
csCallback = new CertStoreCallback();
tsCallback = new TrustStoreCallback();
callbacks = new Callback[]{csCallback, tsCallback};
} else if (csCallback == null) {
csCallback = new CertStoreCallback();
callbacks = new Callback[]{csCallback};
} else if (tsCallback == null) {
tsCallback = new TrustStoreCallback();
callbacks = new Callback[]{tsCallback};
}
try {
_handler.handle(callbacks);
} catch (Exception e) {
throw new XWSSecurityException(e);
}
if (tsCallback.getTrustStore() == null) {
return false;
}
Enumeration aliases = tsCallback.getTrustStore().aliases();
while (aliases.hasMoreElements()) {
String alias = (String) aliases.nextElement();
Certificate certificate = tsCallback.getTrustStore().getCertificate(alias);
if (certificate == null || !"X.509".equals(certificate.getType())) {
continue;
}
X509Certificate x509Cert = (X509Certificate) certificate;
if (x509Cert != null && x509Cert.equals(cert)) {
return true;
}
}
return false;
} catch (Exception e) {
throw new XWSSecurityException(e);
}
}
/**
* @param keyIdMatch
* KeyIdentifier to search for
* @return the matching Certificate
*/
public X509Certificate getMatchingCertificate(Map context, byte[] keyIdMatch)
throws XWSSecurityException {
Subject subject = getSubject(context);
if (subject != null) {
Set set = subject.getPrivateCredentials(X500PrivateCredential.class);
if (set != null) {
Iterator it = set.iterator();
while (it.hasNext()) {
X500PrivateCredential cred = (X500PrivateCredential)it.next();
X509Certificate cert = cred.getCertificate();
if (matchesKeyIdentifier(keyIdMatch, cert))
return cert;
}
}
}
PrivateKeyCallback.Request request = new PrivateKeyCallback.SubjectKeyIDRequest(
keyIdMatch);
PrivateKeyCallback pkCallback = new PrivateKeyCallback(request);
TrustStoreCallback tsCallback = new TrustStoreCallback();
Callback[] callbacks = new Callback[] { pkCallback, tsCallback };
try {
_handler.handle(callbacks);
} catch (Exception e) {
throw new XWSSecurityException(e);
}
Certificate[] chain = pkCallback.getChain();
if (chain != null) {
for (int i=0; i() {
public Object run() {
String x500Name = "CN=" + username;
Principal principal = new X500Principal(x500Name);
subject.getPrincipals().add(principal);
subject.getPrivateCredentials().add(password);
return null;
}
});
}
public void updateOtherPartySubject(
final Subject subject,
final X509Certificate cert) {
AccessController.doPrivileged(
new PrivilegedAction