From 7194e864476a93e05faf762dfded0cc6055ba8a6 Mon Sep 17 00:00:00 2001
From: Matthew Swift <matthew.swift@forgerock.com>
Date: Tue, 20 Sep 2011 08:41:42 +0000
Subject: [PATCH] Issue OPENDJ-262: Implement pass through authentication (PTA)
---
opends/src/server/org/opends/server/extensions/LDAPPassThroughAuthenticationPolicyFactory.java | 143 ++++++++++++++++++++++++++++++++++++++++++++---
1 files changed, 133 insertions(+), 10 deletions(-)
diff --git a/opends/src/server/org/opends/server/extensions/LDAPPassThroughAuthenticationPolicyFactory.java b/opends/src/server/org/opends/server/extensions/LDAPPassThroughAuthenticationPolicyFactory.java
index 02702cd..304f2a8 100644
--- a/opends/src/server/org/opends/server/extensions/LDAPPassThroughAuthenticationPolicyFactory.java
+++ b/opends/src/server/org/opends/server/extensions/LDAPPassThroughAuthenticationPolicyFactory.java
@@ -32,9 +32,10 @@
import static org.opends.messages.ExtensionMessages.*;
import static org.opends.server.loggers.debug.DebugLogger.debugEnabled;
import static org.opends.server.protocols.ldap.LDAPConstants.*;
+import static org.opends.server.util.StaticUtils.getExceptionMessage;
+import static org.opends.server.util.StaticUtils.getFileForPath;
-import java.io.Closeable;
-import java.io.IOException;
+import java.io.*;
import java.net.*;
import java.util.*;
import java.util.concurrent.*;
@@ -47,6 +48,8 @@
import org.opends.messages.Message;
import org.opends.server.admin.server.ConfigurationChangeListener;
+import org.opends.server.admin.std.meta.
+ LDAPPassThroughAuthenticationPolicyCfgDefn.MappingPolicy;
import org.opends.server.admin.std.server.*;
import org.opends.server.api.*;
import org.opends.server.config.ConfigException;
@@ -69,7 +72,6 @@
{
// TODO: handle password policy response controls? AD?
- // TODO: provide alternative cfg for search password.
// TODO: custom aliveness pings
// TODO: manage account lockout
// TODO: cache password
@@ -1926,6 +1928,22 @@
{
this.cfg = cfg;
+ // First obtain the mapped search password if needed, ignoring any errors
+ // since these should have already been detected during configuration
+ // validation.
+ final String mappedSearchPassword;
+ if (cfg.getMappingPolicy() == MappingPolicy.MAPPED_SEARCH
+ && cfg.getMappedSearchBindDN() != null
+ && !cfg.getMappedSearchBindDN().isNullDN())
+ {
+ mappedSearchPassword = getMappedSearchBindPassword(cfg,
+ new LinkedList<Message>());
+ }
+ else
+ {
+ mappedSearchPassword = null;
+ }
+
// Use two pools per server: one for authentication (bind) and one for
// searches. Even if the searches are performed anonymously we cannot use
// the same pool, otherwise they will be performed as the most recently
@@ -1947,7 +1965,7 @@
searchPool[index] = new ConnectionPool(
new AuthenticatedConnectionFactory(factory,
cfg.getMappedSearchBindDN(),
- cfg.getMappedSearchBindPassword()));
+ mappedSearchPassword));
bindPool[index++] = new ConnectionPool(factory);
}
primarySearchLoadBalancer = new RoundRobinLoadBalancer(searchPool,
@@ -1972,7 +1990,7 @@
searchPool[index] = new ConnectionPool(
new AuthenticatedConnectionFactory(factory,
cfg.getMappedSearchBindDN(),
- cfg.getMappedSearchBindPassword()));
+ mappedSearchPassword));
bindPool[index++] = new ConnectionPool(factory);
}
final RoundRobinLoadBalancer secondarySearchLoadBalancer =
@@ -2098,6 +2116,100 @@
+//Get the search bind password performing mapped searches.
+ //
+ // We will offer several places to look for the password, and we will
+ // do so in the following order:
+ //
+ // - In a specified Java property
+ // - In a specified environment variable
+ // - In a specified file on the server filesystem.
+ // - As the value of a configuration attribute.
+ //
+ // In any case, the password must be in the clear.
+ private static String getMappedSearchBindPassword(
+ final LDAPPassThroughAuthenticationPolicyCfg cfg,
+ final List<Message> unacceptableReasons)
+ {
+ String password = null;
+
+ if (cfg.getMappedSearchBindPasswordProperty() != null)
+ {
+ String propertyName = cfg.getMappedSearchBindPasswordProperty();
+ password = System.getProperty(propertyName);
+ if (password == null)
+ {
+ unacceptableReasons.add(ERR_LDAP_PTA_PWD_PROPERTY_NOT_SET.get(
+ String.valueOf(cfg.dn()), String.valueOf(propertyName)));
+ }
+ }
+ else if (cfg.getMappedSearchBindPasswordEnvironmentVariable() != null)
+ {
+ String envVarName = cfg.getMappedSearchBindPasswordEnvironmentVariable();
+ password = System.getenv(envVarName);
+ if (password == null)
+ {
+ unacceptableReasons.add(ERR_LDAP_PTA_PWD_ENVAR_NOT_SET.get(
+ String.valueOf(cfg.dn()), String.valueOf(envVarName)));
+ }
+ }
+ else if (cfg.getMappedSearchBindPasswordFile() != null)
+ {
+ String fileName = cfg.getMappedSearchBindPasswordFile();
+ File passwordFile = getFileForPath(fileName);
+ if (!passwordFile.exists())
+ {
+ unacceptableReasons.add(ERR_LDAP_PTA_PWD_NO_SUCH_FILE.get(
+ String.valueOf(cfg.dn()), String.valueOf(fileName)));
+ }
+ else
+ {
+ BufferedReader br = null;
+ try
+ {
+ br = new BufferedReader(new FileReader(passwordFile));
+ password = br.readLine();
+ if (password == null)
+ {
+ unacceptableReasons.add(ERR_LDAP_PTA_PWD_FILE_EMPTY.get(
+ String.valueOf(cfg.dn()), String.valueOf(fileName)));
+ }
+ }
+ catch (IOException e)
+ {
+ unacceptableReasons.add(ERR_LDAP_PTA_PWD_FILE_CANNOT_READ.get(
+ String.valueOf(cfg.dn()), String.valueOf(fileName),
+ getExceptionMessage(e)));
+ }
+ finally
+ {
+ try
+ {
+ br.close();
+ }
+ catch (Exception e)
+ {
+ // Ignored.
+ }
+ }
+ }
+ }
+ else if (cfg.getMappedSearchBindPassword() != null)
+ {
+ password = cfg.getMappedSearchBindPassword();
+ }
+ else
+ {
+ // Password wasn't defined anywhere.
+ unacceptableReasons
+ .add(ERR_LDAP_PTA_NO_PWD.get(String.valueOf(cfg.dn())));
+ }
+
+ return password;
+ }
+
+
+
private static boolean isServerAddressValid(
final LDAPPassThroughAuthenticationPolicyCfg configuration,
final List<Message> unacceptableReasons, final String hostPort)
@@ -2189,7 +2301,7 @@
*/
@Override
public boolean isConfigurationAcceptable(
- final LDAPPassThroughAuthenticationPolicyCfg configuration,
+ final LDAPPassThroughAuthenticationPolicyCfg cfg,
final List<Message> unacceptableReasons)
{
// Check that the port numbers are valid. We won't actually try and connect
@@ -2197,18 +2309,29 @@
// capabilities).
boolean configurationIsAcceptable = true;
- for (final String hostPort : configuration.getPrimaryRemoteLDAPServer())
+ for (final String hostPort : cfg.getPrimaryRemoteLDAPServer())
{
- configurationIsAcceptable &= isServerAddressValid(configuration,
+ configurationIsAcceptable &= isServerAddressValid(cfg,
unacceptableReasons, hostPort);
}
- for (final String hostPort : configuration.getSecondaryRemoteLDAPServer())
+ for (final String hostPort : cfg.getSecondaryRemoteLDAPServer())
{
- configurationIsAcceptable &= isServerAddressValid(configuration,
+ configurationIsAcceptable &= isServerAddressValid(cfg,
unacceptableReasons, hostPort);
}
+ // Ensure that the search bind password is defined somewhere.
+ if (cfg.getMappingPolicy() == MappingPolicy.MAPPED_SEARCH
+ && cfg.getMappedSearchBindDN() != null
+ && !cfg.getMappedSearchBindDN().isNullDN())
+ {
+ if (getMappedSearchBindPassword(cfg, unacceptableReasons) == null)
+ {
+ configurationIsAcceptable = false;
+ }
+ }
+
return configurationIsAcceptable;
}
}
--
Gitblit v1.10.0