Skip to content

Commit

Permalink
Merge pull request #7 from kwart/ssl-for-ldap
Browse files Browse the repository at this point in the history
Add support for SSL (LDAPs) - as an additional trasport layer
  • Loading branch information
kwart authored Sep 4, 2017
2 parents 3397227 + 8c322ed commit a4adb61
Show file tree
Hide file tree
Showing 4 changed files with 198 additions and 63 deletions.
149 changes: 90 additions & 59 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ Simple all-in-one LDAP server (wrapped [ApacheDS](http://directory.apache.org/ap

You don't need any configuration files to get it working. Just launch the JAR and that's it.

Server data are not persisted, they just live in memory.

## Download

Download latest tag from [GitHub releases](https://github.com/kwart/ldap-server/releases)
Expand All @@ -25,81 +27,110 @@ You can simply build the software yourself.

You should have [git](http://git-scm.com/) installed

$ git clone git://github.com/kwart/ldap-server.git
```
git clone git://github.com/kwart/ldap-server.git
```

or you can download [current sources as a zip file](https://github.com/kwart/ldap-server/archive/master.zip)

### How to build it

You need to have [Maven](http://maven.apache.org/) installed

$ cd ldap-server
$ mvn clean package
```bash
mvn clean package
```

### How to run it

$ java -jar ldap-server.jar [data.ldif]
```bash
java -jar ldap-server.jar [data.ldif]
```

#### Help

$ java -jar ldap-server.jar --help
The ldap-server is a simple LDAP server implementation based on ApacheDS. It
creates one user partition with root 'dc=jboss,dc=org'.

Usage: java -jar ldap-server.jar [options] [LDIFs to import]
Options:
--bind, -b
takes [bindAddress] as a parameter and binds the LDAP server on the
address
Default: 0.0.0.0
--help, -h
shows this help and exits
Default: false
--port, -p
takes [portNumber] as a parameter and binds the LDAP server on that port
Default: 10389

Examples:

$ java -jar ldap-server.jar users.ldif
Starts LDAP server on port 10389 (all interfaces) and imports users.ldif

$ java -jar ldap-server.jar -b 127.0.0.1 -p 389
Starts LDAP server on address 127.0.0.1:389 and imports default data (one user
entry 'uid=jduke,ou=Users,dc=jboss,dc=org'
```
$ java -jar target/ldap-server.jar --help
The ldap-server is a simple LDAP server implementation based on ApacheDS. It
creates one user partition with root 'dc=jboss,dc=org'.
Usage: java -jar ldap-server.jar [options] [LDIFs to import]
Options:
--allow-anonymous, -a
allows anonymous bind to the server
Default: false
--bind, -b
takes [bindAddress] as a parameter and binds the LDAP server on the
address
Default: 0.0.0.0
--help, -h
shows this help and exits
Default: false
--port, -p
takes [portNumber] as a parameter and binds the LDAP server on that port
Default: 10389
--ssl-enabled-ciphersuite, -scs
takes [sslCipherSuite] as argument and enables it for 'ldaps'. Can be
used multiple times.
--ssl-enabled-protocol, -sep
takes [sslProtocolName] as argument and enables it for 'ldaps'. Can be
used multiple times. If the argument is not provided following are used:
TLSv1, TLSv1.1, TLSv1.2
--ssl-need-client-auth, -snc
enables SSL 'needClientAuth' flag
Default: false
--ssl-port, -sp
adds SSL transport layer (i.e. 'ldaps' protocol). It takes [portNumber]
as a parameter and binds the LDAPs server on the port
--ssl-want-client-auth, -swc
enables SSL 'wantClientAuth' flag
Default: false
Examples:
$ java -jar ldap-server.jar users.ldif
Starts LDAP server on port 10389 (all interfaces) and imports users.ldif
$ java -jar ldap-server.jar -b 127.0.0.1 -p 389
Starts LDAP server on address 127.0.0.1:389 and imports default data (one user
entry 'uid=jduke,ou=Users,dc=jboss,dc=org'
```

## Default LDIF

dn: dc=jboss,dc=org
dc: jboss
objectClass: top
objectClass: domain

dn: ou=Users,dc=jboss,dc=org
objectClass: organizationalUnit
objectClass: top
ou: Users

dn: uid=jduke,ou=Users,dc=jboss,dc=org
objectClass: top
objectClass: person
objectClass: inetOrgPerson
cn: Java Duke
sn: duke
uid: jduke
userPassword: theduke

dn: ou=Roles,dc=jboss,dc=org
objectclass: top
objectclass: organizationalUnit
ou: Roles

dn: cn=Admin,ou=Roles,dc=jboss,dc=org
objectClass: top
objectClass: groupOfNames
cn: Admin
member: uid=jduke,ou=Users,dc=jboss,dc=org

```
version: 1
dn: dc=jboss,dc=org
dc: jboss
objectClass: top
objectClass: domain
dn: ou=Users,dc=jboss,dc=org
objectClass: organizationalUnit
objectClass: top
ou: Users
dn: uid=jduke,ou=Users,dc=jboss,dc=org
objectClass: top
objectClass: person
objectClass: inetOrgPerson
cn: Java Duke
sn: duke
uid: jduke
userPassword: theduke
dn: ou=Roles,dc=jboss,dc=org
objectclass: top
objectclass: organizationalUnit
ou: Roles
dn: cn=Admin,ou=Roles,dc=jboss,dc=org
objectClass: top
objectClass: groupOfNames
cn: Admin
member: uid=jduke,ou=Users,dc=jboss,dc=org
```

## License

Expand Down
40 changes: 39 additions & 1 deletion src/main/java/org/jboss/test/ldap/CLIArguments.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public class CLIArguments {

@Parameter(names = { "--allow-anonymous", "-a" }, description = "allows anonymous bind to the server")
private boolean allowAnonymous;

@Parameter(names = { "--port",
"-p" }, description = "takes [portNumber] as a parameter and binds the LDAP server on that port")
private int port = DEFAULT_PORT;
Expand All @@ -50,6 +50,24 @@ public class CLIArguments {
"-b" }, description = "takes [bindAddress] as a parameter and binds the LDAP server on the address")
private String bindAddress = DEFAULT_ADDR;

@Parameter(names = { "--ssl-port",
"-sp" }, description = "adds SSL transport layer (i.e. 'ldaps' protocol). It takes [portNumber] as a parameter and binds the LDAPs server on the port")
private Integer sslPort = null;

@Parameter(names = { "--ssl-need-client-auth", "-snc" }, description = "enables SSL 'needClientAuth' flag")
private boolean sslNeedClientAuth;

@Parameter(names = { "--ssl-want-client-auth", "-swc" }, description = "enables SSL 'wantClientAuth' flag")
private boolean sslWantClientAuth;

@Parameter(names = { "--ssl-enabled-protocol",
"-sep" }, description = "takes [sslProtocolName] as argument and enables it for 'ldaps'. Can be used multiple times."
+ " If the argument is not provided following are used: TLSv1, TLSv1.1, TLSv1.2")
private List<String> sslEnabledProtocols;

@Parameter(names = { "--ssl-enabled-ciphersuite", "-scs" }, description = "takes [sslCipherSuite] as argument and enables it for 'ldaps'. Can be used multiple times.")
private List<String> sslCipherSuite;

public List<String> getLdifFiles() {
return ldifFiles;
}
Expand All @@ -70,4 +88,24 @@ public boolean isAllowAnonymous() {
return allowAnonymous;
}

public Integer getSslPort() {
return sslPort;
}

public boolean isSslNeedClientAuth() {
return sslNeedClientAuth;
}

public boolean isSslWantClientAuth() {
return sslWantClientAuth;
}

public List<String> getSslEnabledProtocols() {
return sslEnabledProtocols;
}

public List<String> getSslCipherSuite() {
return sslCipherSuite;
}

}
18 changes: 17 additions & 1 deletion src/main/java/org/jboss/test/ldap/LdapServer.java
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ public static void main(String[] args) throws Exception {
jCmd.setUsageTail("Examples:\n\n" //
+ "$ java -jar ldap-server.jar users.ldif\n" //
+ " Starts LDAP server on port 10389 (all interfaces) and imports users.ldif\n\n" //
+ "$ java -jar ldap-server.jar -sp 10636 users.ldif\n" //
+ " Starts LDAP server on port 10389 and LDAPs on port 10636 and imports the LDIF\n\n" //
+ "$ java -jar ldap-server.jar -b 127.0.0.1 -p 389\n" //
+ " Starts LDAP server on address 127.0.0.1:389 and imports default data (one user entry 'uid=jduke,ou=Users,dc=jboss,dc=org'");
if (cliArguments.isHelp()) {
Expand Down Expand Up @@ -88,7 +90,18 @@ public LdapServer(CLIArguments cliArguments) throws Exception {
importLdif(cliArguments.getLdifFiles());

ldapServer = new org.apache.directory.server.ldap.LdapServer();
ldapServer.setTransports(new TcpTransport(cliArguments.getBindAddress(), cliArguments.getPort()));
TcpTransport tcp = new TcpTransport(cliArguments.getBindAddress(), cliArguments.getPort());
if (cliArguments.getSslPort() != null) {
TcpTransport ldapsTcp = new TcpTransport(cliArguments.getBindAddress(), cliArguments.getSslPort());
ldapsTcp.setEnableSSL(true);
ldapsTcp.setEnabledProtocols(cliArguments.getSslEnabledProtocols());
ldapsTcp.setEnabledCiphers(cliArguments.getSslCipherSuite());
ldapsTcp.setNeedClientAuth(cliArguments.isSslNeedClientAuth());
ldapsTcp.setWantClientAuth(cliArguments.isSslWantClientAuth());
ldapServer.setTransports(tcp, ldapsTcp);
} else {
ldapServer.setTransports(tcp);
}
ldapServer.setDirectoryService(directoryService);

ldapServer.start();
Expand All @@ -101,6 +114,9 @@ public LdapServer(CLIArguments cliArguments) throws Exception {
host = cliArguments.getBindAddress();
}
System.out.println("URL: ldap://" + formatPossibleIpv6(host) + ":" + cliArguments.getPort());
if (cliArguments.getSslPort() != null) {
System.out.println(" ldaps://" + formatPossibleIpv6(host) + ":" + cliArguments.getSslPort());
}
System.out.println("User DN: uid=admin,ou=system");
System.out.println("Password: secret");
System.out.println("LDAP server started in " + (System.currentTimeMillis() - startTime) + "ms");
Expand Down
54 changes: 52 additions & 2 deletions src/main/java/org/jboss/test/ldap/LdapTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@

package org.jboss.test.ldap;

import java.net.Socket;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Properties;

import javax.naming.Context;
Expand All @@ -29,6 +35,10 @@
import javax.naming.directory.SearchResult;
import javax.naming.ldap.InitialLdapContext;
import javax.naming.ldap.LdapContext;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509ExtendedTrustManager;

/**
* A simple test of running LDAP server.
Expand All @@ -44,16 +54,26 @@ public class LdapTest {
*
* @param args
* @throws NamingException
* @throws NoSuchAlgorithmException
* @throws KeyManagementException
*/
public static void main(String[] args) throws NamingException {
final String ldapUrl = "ldap://[::1]:10389";
public static void main(String[] args) throws NamingException, NoSuchAlgorithmException, KeyManagementException {
String ldapUrl = "ldap://[::1]:10389";

if (Boolean.parseBoolean(System.getProperty("ldaptest.ssl"))) {
SSLContext sslCtx = SSLContext.getInstance("TLS");
sslCtx.init(null, new TrustManager[] { new NoVerificationTrustManager() }, new SecureRandom());
SSLContext.setDefault(sslCtx);
ldapUrl = "ldaps://[::1]:10636";
}
final Properties env = new Properties();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, ldapUrl);
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, "uid=admin,ou=system");
env.put(Context.SECURITY_CREDENTIALS, "secret");
final LdapContext ctx = new InitialLdapContext(env, null);

// ctx.setRequestControls(null);
final SearchControls searchControls = new SearchControls();
searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
Expand All @@ -66,4 +86,34 @@ public static void main(String[] args) throws NamingException {
namingEnum.close();
ctx.close();
}

public static class NoVerificationTrustManager extends X509ExtendedTrustManager {

public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
}

public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
}

public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}

@Override
public void checkClientTrusted(X509Certificate[] chain, String authType, Socket socket) throws CertificateException {
}

@Override
public void checkClientTrusted(X509Certificate[] chain, String authType, SSLEngine engine) throws CertificateException {
}

@Override
public void checkServerTrusted(X509Certificate[] chain, String authType, Socket socket) throws CertificateException {
}

@Override
public void checkServerTrusted(X509Certificate[] chain, String authType, SSLEngine engine) throws CertificateException {
}

}
}

0 comments on commit a4adb61

Please sign in to comment.