Skip to content

Commit

Permalink
Merge pull request #812 from honza889/ELY-1138
Browse files Browse the repository at this point in the history
[ELY-1138][JBEAP-10772] certificate-revocation-list into Elytron XML
  • Loading branch information
darranl committed May 18, 2017
2 parents d9f748e + 13ecc15 commit b0ad984
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import static javax.xml.stream.XMLStreamConstants.END_ELEMENT;
import static javax.xml.stream.XMLStreamConstants.PROCESSING_INSTRUCTION;
import static javax.xml.stream.XMLStreamConstants.START_ELEMENT;
import static org.wildfly.common.Assert.checkMinimumParameter;
import static org.wildfly.common.Assert.checkNotNullParam;
import static org.wildfly.security._private.ElytronMessages.xmlLog;

Expand All @@ -37,6 +38,7 @@
import java.security.GeneralSecurityException;
import java.security.KeyPair;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.Provider;
Expand Down Expand Up @@ -109,6 +111,7 @@
import org.wildfly.security.ssl.CipherSuiteSelector;
import org.wildfly.security.ssl.ProtocolSelector;
import org.wildfly.security.ssl.SSLContextBuilder;
import org.wildfly.security.ssl.X509CRLExtendedTrustManager;
import org.wildfly.security.util.CodePointIterator;
import org.wildfly.security.util.ProviderUtil;
import org.wildfly.security.util.ServiceLoaderSupplier;
Expand Down Expand Up @@ -393,6 +396,8 @@ private static void parseSslContextType(final ConfigurationXMLStreamReader reade
PrivateKeyKeyStoreEntryCredentialFactory credentialFactory = null;
ExceptionSupplier<KeyStore, ConfigXMLParseException> trustStoreSupplier = null;
DeferredSupplier<Provider[]> providersSupplier = new DeferredSupplier<>(providers);
TrustManagerBuilder trustManagerBuilder = new TrustManagerBuilder();

while (reader.hasNext()) {
final int tag = reader.nextTag();
if (tag == START_ELEMENT) {
Expand Down Expand Up @@ -437,6 +442,12 @@ private static void parseSslContextType(final ConfigurationXMLStreamReader reade
trustStoreSupplier = parseTrustStoreRefType(reader, keyStoresMap);
break;
}
case "certificate-revocation-list": {
if (isSet(foundBits, 6)) throw reader.unexpectedElement();
foundBits = setBit(foundBits, 6);
parseCertificateRevocationList(reader, trustManagerBuilder);
break;
}
default: throw reader.unexpectedElement();
}
} else if (tag != END_ELEMENT) {
Expand Down Expand Up @@ -466,8 +477,12 @@ private static void parseSslContextType(final ConfigurationXMLStreamReader reade
sslContextBuilder.setKeyManager(builder.build());
}
if (finalTrustStoreSupplier != null) {
KeyStore trustStore = finalTrustStoreSupplier.get();
sslContextBuilder.setTrustManager(createX509TrustManager(trustStore));
trustManagerBuilder.setTrustStore(finalTrustStoreSupplier.get());
try {
sslContextBuilder.setTrustManager(trustManagerBuilder.build());
} catch (GeneralSecurityException e) {
throw new ConfigXMLParseException(e);
}
}
sslContextBuilder.setProviderName(finalProviderName);
sslContextBuilder.setProviderSupplier(finalProvidersSupplier);
Expand All @@ -480,21 +495,87 @@ private static void parseSslContextType(final ConfigurationXMLStreamReader reade
throw reader.unexpectedDocumentEnd();
}

private static X509TrustManager createX509TrustManager(KeyStore keyStore) throws ConfigXMLParseException {
try {
private static class TrustManagerBuilder {
KeyStore trustStore;
boolean crl = false;
InputStream crlStream = null;
int maxCertPath = 5;

void setTrustStore(KeyStore trustStore) {
checkNotNullParam("trustStore", trustStore);
this.trustStore = trustStore;
}

void setCrl() {
this.crl = true;
}

void setCrlStream(InputStream crlStream) {
this.crlStream = crlStream;
}

void setMaxCertPath(int maxCertPath) {
checkMinimumParameter("maxCertPath", 1, maxCertPath);
this.maxCertPath = maxCertPath;
}

X509TrustManager build() throws NoSuchAlgorithmException, KeyStoreException {
final TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(keyStore);
trustManagerFactory.init(trustStore);
if (crl) {
return new X509CRLExtendedTrustManager(trustStore, trustManagerFactory, crlStream, maxCertPath, null);
}
for (TrustManager trustManager : trustManagerFactory.getTrustManagers()) {
if (trustManager instanceof X509TrustManager) {
return (X509TrustManager) trustManager;
}
}
throw ElytronMessages.log.noDefaultTrustManager();
} catch (GeneralSecurityException e) {
throw new ConfigXMLParseException(e);
}
}

private static void parseCertificateRevocationList(ConfigurationXMLStreamReader reader, TrustManagerBuilder builder) throws ConfigXMLParseException {
final int attributeCount = reader.getAttributeCount();
String path = null;
int maxCertPath = 0;
for (int i = 0; i < attributeCount; i ++) {
checkAttributeNamespace(reader, i);
switch (reader.getAttributeLocalName(i)) {
case "path": {
if (path != null) throw reader.unexpectedAttribute(i);
path = reader.getAttributeValueResolved(i);
break;
}
case "maximum-cert-path": {
if (maxCertPath != 0) throw reader.unexpectedAttribute(i);
maxCertPath = reader.getIntAttributeValueResolved(i, 1, Integer.MAX_VALUE);
break;
}
default: throw reader.unexpectedAttribute(i);
}
}
while (reader.hasNext()) {
final int tag = reader.nextTag();
if (tag == START_ELEMENT) {
throw reader.unexpectedElement();
} else if (tag == END_ELEMENT) {
builder.setCrl();
if (path != null) {
try {
builder.setCrlStream(new FileInputStream(path));
} catch (FileNotFoundException e) {
throw new ConfigXMLParseException(e);
}
}
if (maxCertPath != 0) builder.setMaxCertPath(maxCertPath);
return;
} else {
throw reader.unexpectedContent();
}
}
throw reader.unexpectedDocumentEnd();
}

static ExceptionUnaryOperator<RuleNode<SecurityFactory<SSLContext>>, ConfigXMLParseException> parseSslContextRuleType(final ConfigurationXMLStreamReader reader, final Map<String, ExceptionSupplier<SecurityFactory<SSLContext>, ConfigXMLParseException>> sslContextsMap) throws ConfigXMLParseException {
final String attributeName = "use-ssl-context";
final String name = requireSingleAttribute(reader, attributeName);
Expand Down
6 changes: 6 additions & 0 deletions src/main/resources/schema/elytron-1_0.xsd
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@
<xsd:element name="protocol" type="names-list-type" minOccurs="0"/>
<xsd:element name="provider-name" type="name-type" minOccurs="0"/>
<xsd:element name="providers" type="providers-type" minOccurs="0"/>
<xsd:element name="certificate-revocation-list" type="certificate-revocation-list-type" minOccurs="0"/>
</xsd:all>
<xsd:attribute name="name" type="xsd:string" use="required"/>
</xsd:complexType>
Expand Down Expand Up @@ -287,6 +288,11 @@
<xsd:element name="use-provider-sasl-factory" substitutionGroup="abstract-sasl-factories" type="empty-type" />
<xsd:element name="use-service-loader-sasl-factory" substitutionGroup="abstract-sasl-factories" type="module-ref-type" />

<xsd:complexType name="certificate-revocation-list-type">
<xsd:attribute name="path" type="xsd:string" use="optional"/>
<xsd:attribute name="maximum-cert-path" type="xsd:positiveInteger" use="optional"/>
</xsd:complexType>

<xsd:complexType name="key-stores-type">
<xsd:sequence minOccurs="0" maxOccurs="unbounded">
<xsd:element name="key-store" type="key-store-type"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
</key-store>
<key-store name="ladybird" type="JKS">
<file name="target/test-classes/ca/jks/ladybird.keystore"/>
<key-store-clear-password password="Elytron"/>
</key-store>
</key-stores>
<ssl-contexts>
Expand Down

0 comments on commit b0ad984

Please sign in to comment.