From e39c35c8eb165e60b8a9a078dbc7bbf459101727 Mon Sep 17 00:00:00 2001 From: Alon Bar-Lev Date: Mon, 10 Jun 2019 12:59:55 +0300 Subject: [PATCH] LDAP: support servers that do not allow anonymous Although the standard method of transport security of LDAP is startTLS and although rootDSE should support anonymous access, there are some old LDAP implementations that are using non standard ldaps:// and reject anonymous bind. Add ldap.supportAnonymous option to support these servers, default is true per standard and best practice. Change-Id: I594404beececee9f7dcac911b81290e9cbd0b0f4 Signed-off-by: Alon Bar-Lev --- Documentation/config-gerrit.txt | 8 +++++ .../gerrit/server/auth/ldap/Helper.java | 32 +++++++++++++++---- 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/Documentation/config-gerrit.txt b/Documentation/config-gerrit.txt index 160d1d7a43..af9134b484 100644 --- a/Documentation/config-gerrit.txt +++ b/Documentation/config-gerrit.txt @@ -3148,6 +3148,14 @@ If true, Gerrit will perform StartTLS extended operation. + By default, false, StartTLS will not be enabled. +[[ldap.supportAnonymous]]ldap.supportAnonymous:: ++ +If false, Gerrit will provide credentials only at connection open, this is +required for some `LDAP` implementations that do not allow anonymous bind +for StartTLS or for reauthentication. ++ +By default, true. + [[ldap.sslVerify]]ldap.sslVerify:: + If false and ldap.server is an `ldaps://` style URL or `ldap.startTls` diff --git a/java/com/google/gerrit/server/auth/ldap/Helper.java b/java/com/google/gerrit/server/auth/ldap/Helper.java index a53a8c2caf..8e294b7cda 100644 --- a/java/com/google/gerrit/server/auth/ldap/Helper.java +++ b/java/com/google/gerrit/server/auth/ldap/Helper.java @@ -73,6 +73,7 @@ class Helper { private final String password; private final String referral; private final boolean startTls; + private final boolean supportAnonymous; private final boolean sslVerify; private final String authentication; private volatile LdapSchema ldapSchema; @@ -91,6 +92,7 @@ class Helper { this.password = LdapRealm.optional(config, "password", ""); this.referral = LdapRealm.optional(config, "referral", "ignore"); this.startTls = config.getBoolean("ldap", "startTls", false); + this.supportAnonymous = config.getBoolean("ldap", "supportAnonymous", true); this.sslVerify = config.getBoolean("ldap", "sslverify", true); this.groupsVisibleToAll = config.getBoolean("ldap", "groupsVisibleToAll", false); this.authentication = LdapRealm.optional(config, "authentication", "simple"); @@ -170,8 +172,15 @@ class Helper { if ("GSSAPI".equals(authentication)) { return kerberosOpen(env); } + + if (!supportAnonymous && username != null) { + env.put(Context.SECURITY_PRINCIPAL, username); + env.put(Context.SECURITY_CREDENTIALS, password); + } + LdapContext ctx = createContext(env); - if (username != null) { + + if (supportAnonymous && username != null) { ctx.addToEnvironment(Context.SECURITY_PRINCIPAL, username); ctx.addToEnvironment(Context.SECURITY_CREDENTIALS, password); ctx.reconnect(null); @@ -207,12 +216,23 @@ class Helper { DirContext authenticate(String dn, String password) throws AccountException { final Properties env = createContextProperties(); try { + env.put(Context.REFERRAL, referral); + + if (!supportAnonymous) { + env.put(Context.SECURITY_AUTHENTICATION, "simple"); + env.put(Context.SECURITY_PRINCIPAL, dn); + env.put(Context.SECURITY_CREDENTIALS, password); + } + LdapContext ctx = createContext(env); - ctx.addToEnvironment(Context.SECURITY_AUTHENTICATION, "simple"); - ctx.addToEnvironment(Context.SECURITY_PRINCIPAL, dn); - ctx.addToEnvironment(Context.SECURITY_CREDENTIALS, password); - ctx.addToEnvironment(Context.REFERRAL, referral); - ctx.reconnect(null); + + if (supportAnonymous) { + ctx.addToEnvironment(Context.SECURITY_AUTHENTICATION, "simple"); + ctx.addToEnvironment(Context.SECURITY_PRINCIPAL, dn); + ctx.addToEnvironment(Context.SECURITY_CREDENTIALS, password); + ctx.reconnect(null); + } + return ctx; } catch (IOException | NamingException e) { throw new AuthenticationFailedException("Incorrect username or password", e);