From 913b28e9f6662d5422ac0e0a1b4239fe6da789d8 Mon Sep 17 00:00:00 2001 From: Andy Gherna Date: Tue, 7 Aug 2018 16:49:41 -0500 Subject: [PATCH] Inline all methods in Ldap utility - Lets me delete this class entirely. Utility need isn't as widespread as I thought it would be. --- .../github/argherna/pike/BaseLdapHandler.java | 33 +++++- .../java/com/github/argherna/pike/Ldap.java | 108 ------------------ .../java/com/github/argherna/pike/Maps.java | 10 +- .../github/argherna/pike/SearchHandler.java | 32 +++++- 4 files changed, 69 insertions(+), 114 deletions(-) delete mode 100644 src/main/java/com/github/argherna/pike/Ldap.java diff --git a/src/main/java/com/github/argherna/pike/BaseLdapHandler.java b/src/main/java/com/github/argherna/pike/BaseLdapHandler.java index ccae32f..7883e7d 100644 --- a/src/main/java/com/github/argherna/pike/BaseLdapHandler.java +++ b/src/main/java/com/github/argherna/pike/BaseLdapHandler.java @@ -1,15 +1,23 @@ package com.github.argherna.pike; import java.io.IOException; +import java.util.Hashtable; import java.util.List; +import java.util.logging.Logger; -import javax.naming.ldap.LdapContext; +import javax.naming.Context; +import javax.naming.directory.DirContext; +import javax.naming.ldap.InitialLdapContext; +import javax.naming.ldap.StartTlsRequest; +import javax.naming.ldap.StartTlsResponse; import com.sun.net.httpserver.HttpExchange; import com.sun.net.httpserver.HttpHandler; abstract class BaseLdapHandler implements HttpHandler { + private static final Logger LOGGER = Logger.getLogger(BaseLdapHandler.class.getName()); + @Override public void handle(HttpExchange exchange) throws IOException { var headers = exchange.getRequestHeaders(); @@ -46,9 +54,28 @@ private void internalDoHtml(HttpExchange exchange) throws IOException { abstract void doJson(HttpExchange exchange) throws IOException; - LdapContext getLdapContext() throws IOException { + DirContext getLdapContext() throws IOException { try { - return Ldap.createLdapContext(Settings.getActiveConnectionName()); + var connection = Settings.getConnectionSettings(Settings.getActiveConnectionName()); + var env = new Hashtable(); + env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); + env.put(Context.PROVIDER_URL, connection.getLdapUrl()); + var ldapContext = new InitialLdapContext(env, null); + if (connection.getUseStartTls()) { + LOGGER.fine("Starting TLS session..."); + var tls = (StartTlsResponse) ldapContext.extendedOperation(new StartTlsRequest()); + tls.negotiate(); + } + ldapContext.addToEnvironment(Context.SECURITY_AUTHENTICATION, connection.getAuthType().toLowerCase()); + if (!connection.getAuthType().toLowerCase().equals("none")) { + LOGGER.fine("Authenticating..."); + ldapContext.addToEnvironment(Context.SECURITY_PRINCIPAL, connection.getBindDn()); + ldapContext.addToEnvironment(Context.SECURITY_CREDENTIALS, + new String(Settings.byteArrayToSecretText(connection.getBindDn(), connection.getPassword()))); + } + ldapContext.addToEnvironment(Context.REFERRAL, connection.getReferralPolicy().toLowerCase()); + LOGGER.fine("Ldap context successfully created!"); + return ldapContext; } catch (Exception e) { if (e instanceof IOException) { throw (IOException) e; diff --git a/src/main/java/com/github/argherna/pike/Ldap.java b/src/main/java/com/github/argherna/pike/Ldap.java deleted file mode 100644 index 4ccbdfd..0000000 --- a/src/main/java/com/github/argherna/pike/Ldap.java +++ /dev/null @@ -1,108 +0,0 @@ -package com.github.argherna.pike; - -import java.io.IOException; -import java.net.URI; -import java.security.KeyStoreException; -import java.security.NoSuchAlgorithmException; -import java.security.UnrecoverableKeyException; -import java.security.cert.CertificateException; -import java.util.Hashtable; -import java.util.List; -import java.util.Map; -import java.util.logging.Level; -import java.util.logging.Logger; - -import javax.naming.Context; -import javax.naming.NamingException; -import javax.naming.directory.SearchControls; -import javax.naming.ldap.InitialLdapContext; -import javax.naming.ldap.LdapContext; -import javax.naming.ldap.StartTlsRequest; -import javax.naming.ldap.StartTlsResponse; - -final class Ldap { - - private static final Logger LOGGER = Logger.getLogger(Ldap.class.getName()); - - private Ldap() { - // Empty constructor prevents instantiation. - } - - static String getFilter(Map> parameters) { - return parameters.containsKey("filter") ? parameters.get("filter").get(0) : "(objectClass=*)"; - } - - static int getSearchScope(Map> parameters) { - // Do a subtree search by default. If another (valid) scope is specified - // then search with that. - var scope = SearchControls.SUBTREE_SCOPE; - if (parameters.containsKey("scope")) { - var value = parameters.get("scope").get(0); - if (value.equalsIgnoreCase("object")) { - scope = SearchControls.OBJECT_SCOPE; - } else if (value.equalsIgnoreCase("onelevel")) { - scope = SearchControls.ONELEVEL_SCOPE; - } - } - return scope; - } - - static String[] getReturnAttributes(Map> parameters) { - String[] returningAttributes = null; - if (parameters.containsKey("attr")) { - var value = parameters.get("attr"); - if (value != null && !value.isEmpty()) { - returningAttributes = value.toArray(new String[value.size()]); - } - } - return returningAttributes; - } - - static SearchControls getSearchControls(Map> parameters) { - var searchControls = new SearchControls(); - searchControls.setSearchScope(getSearchScope(parameters)); - searchControls.setReturningAttributes(getReturnAttributes(parameters)); - return searchControls; - } - - static LdapContext createLdapContext(String connectionName) throws IOException, NamingException, - NoSuchAlgorithmException, CertificateException, KeyStoreException, UnrecoverableKeyException { - var connection = Settings.getConnectionSettings(connectionName); - var env = new Hashtable(); - env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); - env.put(Context.PROVIDER_URL, connection.getLdapUrl()); - var ldapContext = new InitialLdapContext(env, null); - if (connection.getUseStartTls()) { - LOGGER.fine("Starting TLS session..."); - var tls = (StartTlsResponse) ldapContext.extendedOperation(new StartTlsRequest()); - tls.negotiate(); - } - ldapContext.addToEnvironment(Context.SECURITY_AUTHENTICATION, connection.getAuthType().toLowerCase()); - if (!connection.getAuthType().toLowerCase().equals("none")) { - LOGGER.fine("Authenticating..."); - ldapContext.addToEnvironment(Context.SECURITY_PRINCIPAL, connection.getBindDn()); - ldapContext.addToEnvironment(Context.SECURITY_CREDENTIALS, - new String(Settings.byteArrayToSecretText(connection.getBindDn(), connection.getPassword()))); - } - ldapContext.addToEnvironment(Context.REFERRAL, connection.getReferralPolicy().toLowerCase()); - LOGGER.fine("Ldap context successfully created!"); - return ldapContext; - } - - static String getContextInfo(Context context, String envProperty) { - try { - var env = context.getEnvironment(); - return (String) env.get(envProperty); - } catch (NamingException e) { - LOGGER.log(Level.FINE, String.format("Failed to get %s, returning null.", envProperty), e); - return null; - } - } - - static String getLdapHost(String ldapUrl) { - if (Strings.isNullOrEmpty(ldapUrl)) { - return "unknown"; - } - return URI.create(ldapUrl).getHost(); - } -} diff --git a/src/main/java/com/github/argherna/pike/Maps.java b/src/main/java/com/github/argherna/pike/Maps.java index ace97de..011f006 100644 --- a/src/main/java/com/github/argherna/pike/Maps.java +++ b/src/main/java/com/github/argherna/pike/Maps.java @@ -1,5 +1,6 @@ package com.github.argherna.pike; +import java.net.URI; import java.util.ArrayList; import java.util.Map; import java.util.stream.Collectors; @@ -18,13 +19,20 @@ static Map toMap(Settings.ConnectionSettings connSettings) { return Map .of("name", Strings.nullToEmpty(connSettings.getName()), "ldapUrl", Strings.nullToEmpty(connSettings.getLdapUrl()), "host", - Ldap.getLdapHost(Strings.nullToEmpty(connSettings.getLdapUrl())), "baseDn", + getLdapHost(Strings.nullToEmpty(connSettings.getLdapUrl())), "baseDn", Strings.nullToEmpty(connSettings.getBaseDn()), "authType", Strings.nullToEmpty(connSettings.getAuthType()), "bindDn", Strings.nullToEmpty(connSettings.getBindDn()), "useStartTls", connSettings.getUseStartTls()) .entrySet().stream().filter(e -> e.getValue().toString().length() > 0) .collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue())); } + private static String getLdapHost(String ldapUrl) { + if (Strings.isNullOrEmpty(ldapUrl)) { + return "unknown"; + } + return URI.create(ldapUrl).getHost(); + } + static Map toMap(Settings.SearchSettings searchSettings) { return Map .of("name", Strings.nullToEmpty(searchSettings.getName()), "rdn", Strings.nullToEmpty(searchSettings.getRdn()), diff --git a/src/main/java/com/github/argherna/pike/SearchHandler.java b/src/main/java/com/github/argherna/pike/SearchHandler.java index 832d02d..0dfaaeb 100644 --- a/src/main/java/com/github/argherna/pike/SearchHandler.java +++ b/src/main/java/com/github/argherna/pike/SearchHandler.java @@ -12,6 +12,7 @@ import java.util.function.Function; import javax.naming.NamingException; +import javax.naming.directory.SearchControls; import com.sun.net.httpserver.HttpExchange; @@ -54,12 +55,12 @@ void doJson(HttpExchange exchange) throws IOException { if (rawQuery != null && !rawQuery.isEmpty()) { parameters = Http.queryToMap(rawQuery, PARAM_PROCS); rdn = parameters.containsKey("rdn") ? parameters.get("rdn").get(0) : null; - filter = Ldap.getFilter(parameters); + filter = parameters.containsKey("filter") ? parameters.get("filter").get(0) : "(objectClass=*)"; attrs = parameters.get("attr"); scope = parameters.containsKey("scope") ? parameters.get("scope").get(0) : "subtree"; var searchBase = getSearchBase(rdn); - var searchControls = Ldap.getSearchControls(parameters); + var searchControls = getSearchControls(parameters); var results = ldapContext.search(searchBase, filter, searchControls); if (results.hasMoreElements()) { records = new ArrayList<>(); @@ -111,4 +112,31 @@ private String getSearchBase(String rdn) { return sj.toString(); } } + + private SearchControls getSearchControls(Map> parameters) { + // Do a subtree search by default. If another (valid) scope is specified + // then search with that. + var scope = SearchControls.SUBTREE_SCOPE; + if (parameters.containsKey("scope")) { + var value = parameters.get("scope").get(0); + if (value.equalsIgnoreCase("object")) { + scope = SearchControls.OBJECT_SCOPE; + } else if (value.equalsIgnoreCase("onelevel")) { + scope = SearchControls.ONELEVEL_SCOPE; + } + } + + String[] returningAttributes = null; + if (parameters.containsKey("attr")) { + var value = parameters.get("attr"); + if (value != null && !value.isEmpty()) { + returningAttributes = value.toArray(new String[value.size()]); + } + } + + var searchControls = new SearchControls(); + searchControls.setSearchScope(scope); + searchControls.setReturningAttributes(returningAttributes); + return searchControls; + } }