blob: 8a0eeedf62a84e7b649c94a19021fc80db2a84a9 [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.xml.security.stax.impl.securityToken;
import org.apache.xml.security.binding.xmldsig.*;
import org.apache.xml.security.binding.xmldsig11.ECKeyValueType;
import org.apache.xml.security.exceptions.XMLSecurityException;
import org.apache.xml.security.stax.ext.*;
import org.apache.xml.security.stax.impl.util.IDGenerator;
import org.apache.xml.security.stax.securityToken.SecurityTokenConstants.TokenType;
import org.apache.xml.security.stax.securityToken.InboundSecurityToken;
import org.apache.xml.security.stax.securityToken.SecurityTokenConstants;
import org.apache.xml.security.stax.securityToken.SecurityTokenFactory;
import org.apache.xml.security.utils.RFC2253Parser;
import org.apache.xml.security.utils.UnsyncByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.Key;
import java.security.PublicKey;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Map;
/**
* Factory to create SecurityToken Objects from keys in XML
*
*/
public class SecurityTokenFactoryImpl extends SecurityTokenFactory {
public SecurityTokenFactoryImpl() {
}
@Override
public InboundSecurityToken getSecurityToken(KeyInfoType keyInfoType,
SecurityTokenConstants.KeyUsage keyUsage,
XMLSecurityProperties securityProperties,
InboundSecurityContext inboundSecurityContext) throws XMLSecurityException {
if (keyInfoType != null) {
// X509Data
final X509DataType x509DataType =
XMLSecurityUtils.getQNameType(keyInfoType.getContent(), XMLSecurityConstants.TAG_dsig_X509Data);
if (x509DataType != null) {
return getSecurityToken(x509DataType, securityProperties, inboundSecurityContext, keyUsage);
}
// KeyValue
final KeyValueType keyValueType
= XMLSecurityUtils.getQNameType(keyInfoType.getContent(), XMLSecurityConstants.TAG_dsig_KeyValue);
if (keyValueType != null) {
return getSecurityToken(keyValueType, securityProperties, inboundSecurityContext, keyUsage);
}
// KeyName
final String keyName =
XMLSecurityUtils.getQNameType(keyInfoType.getContent(), XMLSecurityConstants.TAG_dsig_KeyName);
if (keyName != null) {
KeyNameSecurityToken token = getSecurityToken(keyName, securityProperties, inboundSecurityContext, keyUsage);
return token;
}
}
// Use a default key if it exists
if (SecurityTokenConstants.KeyUsage_Signature_Verification.equals(keyUsage)
&& securityProperties.getSignatureVerificationKey() != null) {
return getDefaultSecurityToken(securityProperties, inboundSecurityContext, keyUsage);
} else if (SecurityTokenConstants.KeyUsage_Decryption.equals(keyUsage)
&& securityProperties.getDecryptionKey() != null) {
return getDefaultSecurityToken(securityProperties, inboundSecurityContext, keyUsage);
}
throw new XMLSecurityException("stax.noKey", new Object[] {keyUsage});
}
private InboundSecurityToken getDefaultSecurityToken(XMLSecurityProperties securityProperties, final InboundSecurityContext inboundSecurityContext, SecurityTokenConstants.KeyUsage keyUsage) {
AbstractInboundSecurityToken token =
new AbstractInboundSecurityToken(inboundSecurityContext, IDGenerator.generateID(null),
SecurityTokenConstants.KeyIdentifier_NoKeyInfo, false) {
@Override
public TokenType getTokenType() {
return SecurityTokenConstants.DefaultToken;
}
};
setTokenKey(securityProperties, keyUsage, token);
return token;
}
private KeyNameSecurityToken getSecurityToken(String keyName, XMLSecurityProperties securityProperties, InboundSecurityContext inboundSecurityContext,
SecurityTokenConstants.KeyUsage keyUsage) throws XMLSecurityException {
KeyNameSecurityToken token =
new KeyNameSecurityToken(keyName, inboundSecurityContext);
// This if is here to preserve the current behaviour when the SignatureVerificationKey is set
if (SecurityTokenConstants.KeyUsage_Signature_Verification.equals(keyUsage)
&& securityProperties.getSignatureVerificationKey() == null) {
Map<String, Key> keyNameMap = securityProperties.getKeyNameMap();
Key key = keyNameMap.get(keyName);
if (key == null) {
throw new XMLSecurityException("stax.keyNotFoundForName", new Object[] {keyName});
}
if (key instanceof PublicKey) {
token.setPublicKey((PublicKey)key);
} else {
throw new XMLSecurityException("stax.keyTypeNotSupported", new Object[] {key.getClass().getSimpleName()});
}
}
setTokenKey(securityProperties, keyUsage, token);
return token;
}
private static InboundSecurityToken getSecurityToken(KeyValueType keyValueType,
XMLSecurityProperties securityProperties,
InboundSecurityContext inboundSecurityContext,
SecurityTokenConstants.KeyUsage keyUsage)
throws XMLSecurityException {
final RSAKeyValueType rsaKeyValueType =
XMLSecurityUtils.getQNameType(keyValueType.getContent(), XMLSecurityConstants.TAG_dsig_RSAKeyValue);
if (rsaKeyValueType != null) {
RsaKeyValueSecurityToken token =
new RsaKeyValueSecurityToken(rsaKeyValueType, inboundSecurityContext);
setTokenKey(securityProperties, keyUsage, token);
return token;
}
final DSAKeyValueType dsaKeyValueType =
XMLSecurityUtils.getQNameType(keyValueType.getContent(), XMLSecurityConstants.TAG_dsig_DSAKeyValue);
if (dsaKeyValueType != null) {
DsaKeyValueSecurityToken token =
new DsaKeyValueSecurityToken(dsaKeyValueType, inboundSecurityContext);
setTokenKey(securityProperties, keyUsage, token);
return token;
}
final ECKeyValueType ecKeyValueType =
XMLSecurityUtils.getQNameType(keyValueType.getContent(), XMLSecurityConstants.TAG_dsig11_ECKeyValue);
if (ecKeyValueType != null) {
ECKeyValueSecurityToken token =
new ECKeyValueSecurityToken(ecKeyValueType, inboundSecurityContext);
setTokenKey(securityProperties, keyUsage, token);
return token;
}
throw new XMLSecurityException("stax.unsupportedKeyValue");
}
private static InboundSecurityToken getSecurityToken(X509DataType x509DataType,
XMLSecurityProperties securityProperties,
InboundSecurityContext inboundSecurityContext,
SecurityTokenConstants.KeyUsage keyUsage)
throws XMLSecurityException {
// X509Certificate
byte[] certBytes =
XMLSecurityUtils.getQNameType(
x509DataType.getX509IssuerSerialOrX509SKIOrX509SubjectName(),
XMLSecurityConstants.TAG_dsig_X509Certificate
);
if (certBytes != null) {
X509Certificate cert = getCertificateFromBytes(certBytes);
TokenType tokenType = SecurityTokenConstants.X509V3Token;
if (cert.getVersion() == 1) {
tokenType = SecurityTokenConstants.X509V1Token;
}
X509SecurityToken token =
new X509SecurityToken(tokenType, inboundSecurityContext,
IDGenerator.generateID(null), SecurityTokenConstants.KeyIdentifier_X509KeyIdentifier, true);
token.setX509Certificates(new X509Certificate[]{cert});
setTokenKey(securityProperties, keyUsage, token);
return token;
}
// Issuer Serial
final X509IssuerSerialType issuerSerialType =
XMLSecurityUtils.getQNameType(
x509DataType.getX509IssuerSerialOrX509SKIOrX509SubjectName(),
XMLSecurityConstants.TAG_dsig_X509IssuerSerial
);
if (issuerSerialType != null) {
if (issuerSerialType.getX509IssuerName() == null
|| issuerSerialType.getX509SerialNumber() == null
|| SecurityTokenConstants.KeyUsage_Signature_Verification.equals(keyUsage)
&& securityProperties.getSignatureVerificationKey() == null
|| SecurityTokenConstants.KeyUsage_Decryption.equals(keyUsage)
&& securityProperties.getDecryptionKey() == null) {
throw new XMLSecurityException("stax.noKey", new Object[] {keyUsage});
}
X509IssuerSerialSecurityToken token =
new X509IssuerSerialSecurityToken(
SecurityTokenConstants.X509V3Token, inboundSecurityContext, IDGenerator.generateID(null));
token.setIssuerName(issuerSerialType.getX509IssuerName());
token.setSerialNumber(issuerSerialType.getX509SerialNumber());
setTokenKey(securityProperties, keyUsage, token);
return token;
}
// Subject Key Identifier
byte[] skiBytes =
XMLSecurityUtils.getQNameType(
x509DataType.getX509IssuerSerialOrX509SKIOrX509SubjectName(),
XMLSecurityConstants.TAG_dsig_X509SKI
);
if (skiBytes != null) {
if (SecurityTokenConstants.KeyUsage_Signature_Verification.equals(keyUsage)
&& securityProperties.getSignatureVerificationKey() == null
|| SecurityTokenConstants.KeyUsage_Decryption.equals(keyUsage)
&& securityProperties.getDecryptionKey() == null) {
throw new XMLSecurityException("stax.noKey", new Object[] {keyUsage});
}
X509SKISecurityToken token =
new X509SKISecurityToken(
SecurityTokenConstants.X509V3Token, inboundSecurityContext, IDGenerator.generateID(null));
token.setSkiBytes(skiBytes);
setTokenKey(securityProperties, keyUsage, token);
return token;
}
// Subject Name
String subjectName =
XMLSecurityUtils.getQNameType(
x509DataType.getX509IssuerSerialOrX509SKIOrX509SubjectName(),
XMLSecurityConstants.TAG_dsig_X509SubjectName
);
if (subjectName != null) {
if (SecurityTokenConstants.KeyUsage_Signature_Verification.equals(keyUsage)
&& securityProperties.getSignatureVerificationKey() == null
|| SecurityTokenConstants.KeyUsage_Decryption.equals(keyUsage)
&& securityProperties.getDecryptionKey() == null) {
throw new XMLSecurityException("stax.noKey", new Object[] {keyUsage});
}
String normalizedSubjectName =
RFC2253Parser.normalize(subjectName);
X509SubjectNameSecurityToken token =
new X509SubjectNameSecurityToken(
SecurityTokenConstants.X509V3Token, inboundSecurityContext, IDGenerator.generateID(null));
token.setSubjectName(normalizedSubjectName);
setTokenKey(securityProperties, keyUsage, token);
return token;
}
throw new XMLSecurityException("stax.noKey", new Object[] {keyUsage});
}
private static void setTokenKey(XMLSecurityProperties securityProperties, SecurityTokenConstants.KeyUsage keyUsage,
AbstractInboundSecurityToken token) {
Key key = null;
if (SecurityTokenConstants.KeyUsage_Signature_Verification.equals(keyUsage)) {
key = securityProperties.getSignatureVerificationKey();
} else if (SecurityTokenConstants.KeyUsage_Decryption.equals(keyUsage)) {
key = securityProperties.getDecryptionKey();
}
if (key instanceof PublicKey
&& !SecurityTokenConstants.KeyValueToken.equals(token.getTokenType())) {
token.setPublicKey((PublicKey) key);
} else {
token.setSecretKey("", key);
}
}
/**
* Construct an X509Certificate'from the byte array.
* <p></p>
*
* @param data The <code>byte</code> array containing the X509 data
* @return An X509 certificate
* @throws XMLSecurityException
*/
private static X509Certificate getCertificateFromBytes(byte[] data)
throws XMLSecurityException {
try (InputStream in = new UnsyncByteArrayInputStream(data)) {
CertificateFactory factory = CertificateFactory.getInstance("X.509");
return (X509Certificate) factory.generateCertificate(in);
} catch (CertificateException | IOException e) {
throw new XMLSecurityException(e);
}
}
}