Skip to content

Commit

Permalink
[ELY-1616] ldap-key-store requires attribute userPKCS12 on ldap entry…
Browse files Browse the repository at this point in the history
…, even if it should be mandatory
  • Loading branch information
JiriOndrusek committed Jul 31, 2018
1 parent 7b394b6 commit ea58f1b
Show file tree
Hide file tree
Showing 10 changed files with 261 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
import org.wildfly.security.credential.PasswordCredential;
import org.wildfly.security.evidence.Evidence;
import org.wildfly.security.password.Password;
import org.wildfly.security.util.LdapUtil;

/**
* A {@link CredentialLoader} for loading credentials stored within the 'userPassword' attribute of LDAP entries.
Expand Down Expand Up @@ -141,7 +142,7 @@ public <C extends Credential> C getCredential(final Class<C> credentialType, fin
return null;
}
try {
Attribute attribute = attributes.get(userPasswordAttributeName);
Attribute attribute = LdapUtil.getBinaryAttribute(attributes, userPasswordAttributeName);
if (attribute != null) {
final int size = attribute.size();
for (int i = 0; i < size; i++) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import org.wildfly.security.evidence.Evidence;
import org.wildfly.security.evidence.X509PeerCertificateChainEvidence;
import org.wildfly.security.util.ByteIterator;
import org.wildfly.security.util.LdapUtil;

import javax.naming.NamingException;
import javax.naming.directory.Attribute;
Expand Down Expand Up @@ -195,7 +196,7 @@ public void addBinaryLdapAttributes(Collection<String> binaryAttributes) {

@Override
public boolean verifyCertificate(X509Certificate certificate, Attributes attributes) throws NamingException, RealmUnavailableException {
Attribute attribute = attributes.get(ldapAttribute);
Attribute attribute = LdapUtil.getBinaryAttribute(attributes, ldapAttribute);

if (attribute == null) return false;

Expand Down
12 changes: 7 additions & 5 deletions src/main/java/org/wildfly/security/keystore/LdapKeyStoreSpi.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import static org.wildfly.security._private.ElytronMessages.log;

import org.wildfly.common.function.ExceptionSupplier;
import org.wildfly.security.util.LdapUtil;

import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
Expand Down Expand Up @@ -69,6 +70,7 @@ class LdapKeyStoreSpi extends KeyStoreSpi {
private final String CREATE_TIMESTAMP_ATTRIBUTE = "createTimestamp"; // RFC4512
private final String MODIFY_TIMESTAMP_ATTRIBUTE = "modifyTimestamp"; // RFC4512


private final ExceptionSupplier<DirContext, NamingException> dirContextSupplier;
private final String searchPath;
private final int searchScope;
Expand Down Expand Up @@ -186,7 +188,7 @@ public Certificate engineGetCertificate(String alias) {
return null;
}
try {
Attribute attribute = attributes.get(certificateAttribute);
Attribute attribute = LdapUtil.getBinaryAttribute(attributes, certificateAttribute);
if (attribute == null) return null;
byte[] bytes = (byte[]) attribute.get();
if (bytes == null) return null;
Expand All @@ -206,7 +208,7 @@ public Certificate[] engineGetCertificateChain(String alias) {
return null;
}
try {
Attribute attribute = attributes.get(certificateChainAttribute);
Attribute attribute = LdapUtil.getBinaryAttribute(attributes, certificateChainAttribute);
if (attribute == null) return null;
byte[] bytes = (byte[]) attribute.get();
if (bytes == null) return null;
Expand All @@ -227,7 +229,7 @@ public Key engineGetKey(String alias, char[] password) throws NoSuchAlgorithmExc
return null;
}
try {
Attribute attribute = attributes.get(keyAttribute);
Attribute attribute = LdapUtil.getBinaryAttribute(attributes, keyAttribute);
if (attribute == null) return null; // alias does not identify a key-related entry
byte[] bytes = (byte[]) attribute.get();
if (bytes == null) return null; // alias does not identify a key-related entry
Expand Down Expand Up @@ -426,7 +428,7 @@ public int engineSize() {
@Override
public boolean engineIsKeyEntry(String alias) {
Attributes attributes = obtainAliasOrCertificateAttributes(alias, null, new String[]{keyAttribute});
Attribute attribute = attributes == null ? null : attributes.get(keyAttribute);
Attribute attribute = attributes == null ? null : LdapUtil.getBinaryAttribute(attributes, keyAttribute);
if (attribute == null) {
log.tracef("Alias [%s] is not key entry", alias);
return false;
Expand All @@ -443,7 +445,7 @@ public boolean engineIsKeyEntry(String alias) {
public boolean engineIsCertificateEntry(String alias) {
Attributes attributes = obtainAliasOrCertificateAttributes(alias, null, new String[]{certificateAttribute});
if (attributes == null) return false;
Attribute attribute = attributes.get(certificateAttribute);
Attribute attribute = LdapUtil.getBinaryAttribute(attributes, certificateAttribute);
if (attribute == null) return false;
try {
byte[] bytes = (byte[]) attribute.get();
Expand Down
47 changes: 47 additions & 0 deletions src/main/java/org/wildfly/security/util/LdapUtil.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* JBoss, Home of Professional Open Source.
* Copyright 2018 Red Hat, Inc., and individual contributors
* as indicated by the @author tags.
*
* Licensed 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.wildfly.security.util;

import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;

/**
* Utilities for LDAP attributes manipulation.
*
* @author <a href="mailto:jondruse@redhat.com">Jiri Ondrusek</a>
*/
public class LdapUtil {

private static final String BINARY_SUFFIX = ";binary";

/**
* Ldap servers can return binary attributes with suffix ;binary. This method helps to solve this case.
*
* @param attributes Attributes obtained from server
* @param name Name of returned attribute
* @return Attribute with name 'name', 'name;binary' or null if neither of them exists.
*/
public static Attribute getBinaryAttribute(Attributes attributes, String name) {
Attribute retVal = attributes.get(name);
if(retVal == null && !name.endsWith(BINARY_SUFFIX)) {
retVal = attributes.get(name+BINARY_SUFFIX);
}
return retVal;
}
}
33 changes: 33 additions & 0 deletions src/test/java/org/wildfly/security/ldap/KeyStoreSuiteChild.java
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,10 @@ public void testAliases() throws Exception {
@Test
public void testIs() throws Exception {
Assert.assertTrue(keyStore.isCertificateEntry("firefly"));
Assert.assertTrue(keyStore.isCertificateEntry("firefly_binary"));
Assert.assertFalse(keyStore.isCertificateEntry("nonexisting"));
Assert.assertTrue(keyStore.isKeyEntry("firefly"));
Assert.assertTrue(keyStore.isKeyEntry("firefly_binary"));
Assert.assertFalse(keyStore.isKeyEntry("nonexisting"));
}

Expand All @@ -94,6 +96,13 @@ public void testGetCertificate() throws Exception {
Assert.assertEquals("OU=Elytron, O=Elytron, C=UK, ST=Elytron, CN=Firefly", cert.getSubjectDN().toString());
}

@Test
public void testGetCertificateBinary() throws Exception {
X509Certificate cert = (X509Certificate) keyStore.getCertificate("firefly_binary");
Assert.assertNotNull(cert);
Assert.assertEquals("CN=firefly_binary, OU=Elytron, O=Elytron, L=Elytron, ST=Elytron, C=UK", cert.getSubjectDN().toString());
}

@Test
public void testGetAlias() throws Exception {
X509Certificate cert = (X509Certificate) keyStore.getCertificate("firefly");
Expand All @@ -102,6 +111,14 @@ public void testGetAlias() throws Exception {
Assert.assertEquals("firefly", alias);
}

@Test
public void testGetAliasBinary() throws Exception {
X509Certificate cert = (X509Certificate) keyStore.getCertificate("firefly_binary");
Assert.assertNotNull(cert);
String alias = keyStore.getCertificateAlias(cert);
Assert.assertEquals("firefly_binary", alias);
}

@Test
public void testGetCertificateChain() throws Exception {
Certificate[] chain = keyStore.getCertificateChain("firefly");
Expand All @@ -111,13 +128,29 @@ public void testGetCertificateChain() throws Exception {
Assert.assertEquals("O=Root Certificate Authority, EMAILADDRESS=elytron@wildfly.org, C=UK, ST=Elytron, CN=Elytron CA", ((X509Certificate)chain[1]).getSubjectDN().toString());
}

@Test
public void testGetCertificateChainBinary() throws Exception {
Certificate[] chain = keyStore.getCertificateChain("firefly_binary");
Assert.assertNotNull(chain);
Assert.assertEquals(2, chain.length);
Assert.assertEquals("CN=firefly_binary, OU=Elytron, O=Elytron, L=Elytron, ST=Elytron, C=UK", ((X509Certificate)chain[0]).getSubjectDN().toString());
Assert.assertEquals("CN=localhost, OU=Elytron, O=Elytron, L=Elytron, ST=Elytron, C=UK", ((X509Certificate)chain[1]).getSubjectDN().toString());
}

@Test
public void testGetKey() throws Exception {
RSAPrivateCrtKey key = (RSAPrivateCrtKey) keyStore.getKey("firefly", "Elytron".toCharArray());
Assert.assertNotNull(key);
Assert.assertEquals(BigInteger.valueOf(65537), key.getPublicExponent());
}

@Test
public void testGetKeyBinary() throws Exception {
RSAPrivateCrtKey key = (RSAPrivateCrtKey) keyStore.getKey("firefly_binary", "secret".toCharArray());
Assert.assertNotNull(key);
Assert.assertEquals(BigInteger.valueOf(65537), key.getPublicExponent());
}

@Test
public void testGetCreationTime() throws Exception {
Date date = keyStore.getCreationDate("firefly");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,11 @@ public void testBsdCryptUser() throws Exception {
performSimpleNameTest("bsdCryptUser", BSDUnixDESCryptPassword.ALGORITHM_BSD_CRYPT_DES, "cryptPassword".toCharArray());
}

@Test
public void testBsdCryptUserBinary() throws Exception {
performSimpleNameTest("bsdCryptUser_binary", BSDUnixDESCryptPassword.ALGORITHM_BSD_CRYPT_DES, "cryptPassword".toCharArray());
}

@Test
public void testOneTimePasswordUser0() throws Exception {
SupportLevel support = simpleToDnRealm.getCredentialAcquireSupport(PasswordCredential.class, null, null);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,15 @@ public class X509EvidenceVerificationSuiteChild {

@Test
public void testX509Auth() throws Exception {
testX509AuthInternal("scarab");
}

@Test
public void testX509AuthBinary() throws Exception {
testX509AuthInternal("scarab_binary");
}

private void testX509AuthInternal(String name) throws Exception {
SecurityRealm securityRealm = LdapSecurityRealmBuilder.builder()
.setDirContextSupplier(LdapTestSuite.dirContextFactory.create())
.identityMapping()
Expand All @@ -57,7 +65,7 @@ public void testX509Auth() throws Exception {
.build()
.build();

RealmIdentity realmIdentity = securityRealm.getRealmIdentity(new NamePrincipal("scarab"));
RealmIdentity realmIdentity = securityRealm.getRealmIdentity(new NamePrincipal(name));

SupportLevel credentialSupport = realmIdentity.getEvidenceVerifySupport(X509PeerCertificateChainEvidence.class, null);
assertEquals("Identity verification level support", SupportLevel.POSSIBLY_SUPPORTED, credentialSupport);
Expand Down
11 changes: 11 additions & 0 deletions src/test/resources/ldap/elytron-credential-tests.ldif
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,17 @@ uid: bsdCryptUser
userPassword:: e2NyeXB0fV9OLi4uL1RUcHlCeVRWdmRtV0dv
# Password cryptPassword

dn: uid=bsdCryptUser_binary,dc=elytron,dc=wildfly,dc=org
objectClass: top
objectClass: inetOrgPerson
objectClass: person
objectClass: organizationalPerson
cn: bsdCryptUser_binary
sn: bsdCryptUser_binary
uid: bsdCryptUser
userPassword;binary:: e2NyeXB0fV9OLi4uL1RUcHlCeVRWdmRtV0dv
# Password cryptPassword

dn: uid=userToChange,dc=elytron,dc=wildfly,dc=org
objectClass: top
objectClass: inetOrgPerson
Expand Down

0 comments on commit ea58f1b

Please sign in to comment.