summaryrefslogtreecommitdiffstats
path: root/gerrit-server/src/main/java/com/google/gerrit/server/auth/ldap/Helper.java
diff options
context:
space:
mode:
Diffstat (limited to 'gerrit-server/src/main/java/com/google/gerrit/server/auth/ldap/Helper.java')
-rw-r--r--gerrit-server/src/main/java/com/google/gerrit/server/auth/ldap/Helper.java445
1 files changed, 0 insertions, 445 deletions
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/auth/ldap/Helper.java b/gerrit-server/src/main/java/com/google/gerrit/server/auth/ldap/Helper.java
deleted file mode 100644
index fd88845561..0000000000
--- a/gerrit-server/src/main/java/com/google/gerrit/server/auth/ldap/Helper.java
+++ /dev/null
@@ -1,445 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// 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 com.google.gerrit.server.auth.ldap;
-
-import com.google.common.base.Throwables;
-import com.google.common.cache.Cache;
-import com.google.common.collect.ImmutableSet;
-import com.google.gerrit.common.data.ParameterizedString;
-import com.google.gerrit.reviewdb.client.AccountGroup;
-import com.google.gerrit.server.account.AccountException;
-import com.google.gerrit.server.account.AuthenticationFailedException;
-import com.google.gerrit.server.auth.NoSuchUserException;
-import com.google.gerrit.server.config.ConfigUtil;
-import com.google.gerrit.server.config.GerritServerConfig;
-import com.google.gerrit.util.ssl.BlindSSLSocketFactory;
-import com.google.inject.Inject;
-import com.google.inject.Singleton;
-import com.google.inject.name.Named;
-import java.security.PrivilegedActionException;
-import java.security.PrivilegedExceptionAction;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Properties;
-import java.util.Set;
-import java.util.concurrent.TimeUnit;
-import javax.naming.CompositeName;
-import javax.naming.Context;
-import javax.naming.Name;
-import javax.naming.NamingEnumeration;
-import javax.naming.NamingException;
-import javax.naming.PartialResultException;
-import javax.naming.directory.Attribute;
-import javax.naming.directory.DirContext;
-import javax.naming.directory.InitialDirContext;
-import javax.net.ssl.SSLSocketFactory;
-import javax.security.auth.Subject;
-import javax.security.auth.login.LoginContext;
-import javax.security.auth.login.LoginException;
-import org.eclipse.jgit.lib.Config;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-@Singleton
-class Helper {
- private static final Logger log = LoggerFactory.getLogger(Helper.class);
-
- static final String LDAP_UUID = "ldap:";
-
- private final Cache<String, ImmutableSet<String>> parentGroups;
- private final Config config;
- private final String server;
- private final String username;
- private final String password;
- private final String referral;
- private final boolean sslVerify;
- private final String authentication;
- private volatile LdapSchema ldapSchema;
- private final String readTimeoutMillis;
- private final String connectTimeoutMillis;
- private final boolean useConnectionPooling;
- private final boolean groupsVisibleToAll;
-
- @Inject
- Helper(
- @GerritServerConfig Config config,
- @Named(LdapModule.PARENT_GROUPS_CACHE) Cache<String, ImmutableSet<String>> parentGroups) {
- this.config = config;
- this.server = LdapRealm.optional(config, "server");
- this.username = LdapRealm.optional(config, "username");
- this.password = LdapRealm.optional(config, "password", "");
- this.referral = LdapRealm.optional(config, "referral", "ignore");
- this.sslVerify = config.getBoolean("ldap", "sslverify", true);
- this.groupsVisibleToAll = config.getBoolean("ldap", "groupsVisibleToAll", false);
- this.authentication = LdapRealm.optional(config, "authentication", "simple");
- String readTimeout = LdapRealm.optional(config, "readTimeout");
- if (readTimeout != null) {
- readTimeoutMillis =
- Long.toString(ConfigUtil.getTimeUnit(readTimeout, 0, TimeUnit.MILLISECONDS));
- } else {
- readTimeoutMillis = null;
- }
- String connectTimeout = LdapRealm.optional(config, "connectTimeout");
- if (connectTimeout != null) {
- connectTimeoutMillis =
- Long.toString(ConfigUtil.getTimeUnit(connectTimeout, 0, TimeUnit.MILLISECONDS));
- } else {
- connectTimeoutMillis = null;
- }
- this.parentGroups = parentGroups;
- this.useConnectionPooling = LdapRealm.optional(config, "useConnectionPooling", false);
- }
-
- private Properties createContextProperties() {
- final Properties env = new Properties();
- env.put(Context.INITIAL_CONTEXT_FACTORY, LdapRealm.LDAP);
- env.put(Context.PROVIDER_URL, server);
- if (server.startsWith("ldaps:") && !sslVerify) {
- Class<? extends SSLSocketFactory> factory = BlindSSLSocketFactory.class;
- env.put("java.naming.ldap.factory.socket", factory.getName());
- }
- if (readTimeoutMillis != null) {
- env.put("com.sun.jndi.ldap.read.timeout", readTimeoutMillis);
- }
- if (connectTimeoutMillis != null) {
- env.put("com.sun.jndi.ldap.connect.timeout", connectTimeoutMillis);
- }
- if (useConnectionPooling) {
- env.put("com.sun.jndi.ldap.connect.pool", "true");
- }
- return env;
- }
-
- DirContext open() throws NamingException, LoginException {
- final Properties env = createContextProperties();
- env.put(Context.SECURITY_AUTHENTICATION, authentication);
- env.put(Context.REFERRAL, referral);
- if ("GSSAPI".equals(authentication)) {
- return kerberosOpen(env);
- }
- if (username != null) {
- env.put(Context.SECURITY_PRINCIPAL, username);
- env.put(Context.SECURITY_CREDENTIALS, password);
- }
- return new InitialDirContext(env);
- }
-
- private DirContext kerberosOpen(Properties env) throws LoginException, NamingException {
- LoginContext ctx = new LoginContext("KerberosLogin");
- ctx.login();
- Subject subject = ctx.getSubject();
- try {
- return Subject.doAs(
- subject,
- new PrivilegedExceptionAction<DirContext>() {
- @Override
- public DirContext run() throws NamingException {
- return new InitialDirContext(env);
- }
- });
- } catch (PrivilegedActionException e) {
- Throwables.throwIfInstanceOf(e.getException(), NamingException.class);
- Throwables.throwIfInstanceOf(e.getException(), RuntimeException.class);
- log.warn("Internal error", e.getException());
- return null;
- } finally {
- ctx.logout();
- }
- }
-
- DirContext authenticate(String dn, String password) throws AccountException {
- final Properties env = createContextProperties();
- env.put(Context.SECURITY_AUTHENTICATION, "simple");
- env.put(Context.SECURITY_PRINCIPAL, dn);
- env.put(Context.SECURITY_CREDENTIALS, password);
- env.put(Context.REFERRAL, referral);
- try {
- return new InitialDirContext(env);
- } catch (NamingException e) {
- throw new AuthenticationFailedException("Incorrect username or password", e);
- }
- }
-
- LdapSchema getSchema(DirContext ctx) {
- if (ldapSchema == null) {
- synchronized (this) {
- if (ldapSchema == null) {
- ldapSchema = new LdapSchema(ctx);
- }
- }
- }
- return ldapSchema;
- }
-
- LdapQuery.Result findAccount(
- Helper.LdapSchema schema, DirContext ctx, String username, boolean fetchMemberOf)
- throws NamingException, AccountException {
- final HashMap<String, String> params = new HashMap<>();
- params.put(LdapRealm.USERNAME, username);
-
- List<LdapQuery> accountQueryList;
- if (fetchMemberOf && schema.type.accountMemberField() != null) {
- accountQueryList = schema.accountWithMemberOfQueryList;
- } else {
- accountQueryList = schema.accountQueryList;
- }
-
- for (LdapQuery accountQuery : accountQueryList) {
- List<LdapQuery.Result> res = accountQuery.query(ctx, params);
- if (res.size() == 1) {
- return res.get(0);
- } else if (res.size() > 1) {
- throw new AccountException("Duplicate users: " + username);
- }
- }
- throw new NoSuchUserException(username);
- }
-
- Set<AccountGroup.UUID> queryForGroups(
- final DirContext ctx, String username, LdapQuery.Result account) throws NamingException {
- final LdapSchema schema = getSchema(ctx);
- final Set<String> groupDNs = new HashSet<>();
-
- if (!schema.groupMemberQueryList.isEmpty()) {
- final HashMap<String, String> params = new HashMap<>();
-
- if (account == null) {
- try {
- account = findAccount(schema, ctx, username, false);
- } catch (AccountException e) {
- return Collections.emptySet();
- }
- }
- for (String name : schema.groupMemberQueryList.get(0).getParameters()) {
- params.put(name, account.get(name));
- }
-
- params.put(LdapRealm.USERNAME, username);
-
- for (LdapQuery groupMemberQuery : schema.groupMemberQueryList) {
- for (LdapQuery.Result r : groupMemberQuery.query(ctx, params)) {
- recursivelyExpandGroups(groupDNs, schema, ctx, r.getDN());
- }
- }
- }
-
- if (schema.accountMemberField != null) {
- if (account == null || account.getAll(schema.accountMemberField) == null) {
- try {
- account = findAccount(schema, ctx, username, true);
- } catch (AccountException e) {
- return Collections.emptySet();
- }
- }
-
- final Attribute groupAtt = account.getAll(schema.accountMemberField);
- if (groupAtt != null) {
- final NamingEnumeration<?> groups = groupAtt.getAll();
- try {
- while (groups.hasMore()) {
- final String nextDN = (String) groups.next();
- recursivelyExpandGroups(groupDNs, schema, ctx, nextDN);
- }
- } catch (PartialResultException e) {
- // Ignored
- }
- }
- }
-
- final Set<AccountGroup.UUID> actual = new HashSet<>();
- for (String dn : groupDNs) {
- actual.add(new AccountGroup.UUID(LDAP_UUID + dn));
- }
-
- if (actual.isEmpty()) {
- return Collections.emptySet();
- }
- return ImmutableSet.copyOf(actual);
- }
-
- private void recursivelyExpandGroups(
- final Set<String> groupDNs,
- final LdapSchema schema,
- final DirContext ctx,
- final String groupDN) {
- if (groupDNs.add(groupDN)
- && schema.accountMemberField != null
- && schema.accountMemberExpandGroups) {
- ImmutableSet<String> cachedParentsDNs = parentGroups.getIfPresent(groupDN);
- if (cachedParentsDNs == null) {
- // Recursively identify the groups it is a member of.
- ImmutableSet.Builder<String> dns = ImmutableSet.builder();
- try {
- final Name compositeGroupName = new CompositeName().add(groupDN);
- final Attribute in =
- ctx.getAttributes(compositeGroupName, schema.accountMemberFieldArray)
- .get(schema.accountMemberField);
- if (in != null) {
- final NamingEnumeration<?> groups = in.getAll();
- try {
- while (groups.hasMore()) {
- dns.add((String) groups.next());
- }
- } catch (PartialResultException e) {
- // Ignored
- }
- }
- } catch (NamingException e) {
- log.warn("Could not find group {}", groupDN, e);
- }
- cachedParentsDNs = dns.build();
- parentGroups.put(groupDN, cachedParentsDNs);
- }
- for (String dn : cachedParentsDNs) {
- recursivelyExpandGroups(groupDNs, schema, ctx, dn);
- }
- }
- }
-
- public boolean groupsVisibleToAll() {
- return this.groupsVisibleToAll;
- }
-
- class LdapSchema {
- final LdapType type;
-
- final ParameterizedString accountFullName;
- final ParameterizedString accountEmailAddress;
- final ParameterizedString accountSshUserName;
- final String accountMemberField;
- final boolean accountMemberExpandGroups;
- final String[] accountMemberFieldArray;
- final List<LdapQuery> accountQueryList;
- final List<LdapQuery> accountWithMemberOfQueryList;
-
- final List<String> groupBases;
- final SearchScope groupScope;
- final ParameterizedString groupPattern;
- final ParameterizedString groupName;
- final List<LdapQuery> groupMemberQueryList;
-
- LdapSchema(DirContext ctx) {
- type = discoverLdapType(ctx);
- groupMemberQueryList = new ArrayList<>();
- accountQueryList = new ArrayList<>();
- accountWithMemberOfQueryList = new ArrayList<>();
-
- final Set<String> accountAtts = new HashSet<>();
-
- // Group query
- //
-
- groupBases = LdapRealm.optionalList(config, "groupBase");
- groupScope = LdapRealm.scope(config, "groupScope");
- groupPattern = LdapRealm.paramString(config, "groupPattern", type.groupPattern());
- groupName = LdapRealm.paramString(config, "groupName", type.groupName());
- final String groupMemberPattern =
- LdapRealm.optdef(config, "groupMemberPattern", type.groupMemberPattern());
-
- for (String groupBase : groupBases) {
- if (groupMemberPattern != null) {
- final LdapQuery groupMemberQuery =
- new LdapQuery(
- groupBase,
- groupScope,
- new ParameterizedString(groupMemberPattern),
- Collections.<String>emptySet());
- if (groupMemberQuery.getParameters().isEmpty()) {
- throw new IllegalArgumentException("No variables in ldap.groupMemberPattern");
- }
-
- for (String name : groupMemberQuery.getParameters()) {
- accountAtts.add(name);
- }
-
- groupMemberQueryList.add(groupMemberQuery);
- }
- }
-
- // Account query
- //
- accountFullName = LdapRealm.paramString(config, "accountFullName", type.accountFullName());
- if (accountFullName != null) {
- accountAtts.addAll(accountFullName.getParameterNames());
- }
- accountEmailAddress =
- LdapRealm.paramString(config, "accountEmailAddress", type.accountEmailAddress());
- if (accountEmailAddress != null) {
- accountAtts.addAll(accountEmailAddress.getParameterNames());
- }
- accountSshUserName =
- LdapRealm.paramString(config, "accountSshUserName", type.accountSshUserName());
- if (accountSshUserName != null) {
- accountAtts.addAll(accountSshUserName.getParameterNames());
- }
- accountMemberField =
- LdapRealm.optdef(config, "accountMemberField", type.accountMemberField());
- if (accountMemberField != null) {
- accountMemberFieldArray = new String[] {accountMemberField};
- } else {
- accountMemberFieldArray = null;
- }
- accountMemberExpandGroups =
- LdapRealm.optional(config, "accountMemberExpandGroups", type.accountMemberExpandGroups());
-
- final SearchScope accountScope = LdapRealm.scope(config, "accountScope");
- final String accountPattern =
- LdapRealm.reqdef(config, "accountPattern", type.accountPattern());
-
- Set<String> accountWithMemberOfAtts;
- if (accountMemberField != null) {
- accountWithMemberOfAtts = new HashSet<>(accountAtts);
- accountWithMemberOfAtts.add(accountMemberField);
- } else {
- accountWithMemberOfAtts = null;
- }
- for (String accountBase : LdapRealm.requiredList(config, "accountBase")) {
- LdapQuery accountQuery =
- new LdapQuery(
- accountBase, accountScope, new ParameterizedString(accountPattern), accountAtts);
- if (accountQuery.getParameters().isEmpty()) {
- throw new IllegalArgumentException("No variables in ldap.accountPattern");
- }
- accountQueryList.add(accountQuery);
-
- if (accountWithMemberOfAtts != null) {
- LdapQuery accountWithMemberOfQuery =
- new LdapQuery(
- accountBase,
- accountScope,
- new ParameterizedString(accountPattern),
- accountWithMemberOfAtts);
- accountWithMemberOfQueryList.add(accountWithMemberOfQuery);
- }
- }
- }
-
- LdapType discoverLdapType(DirContext ctx) {
- try {
- return LdapType.guessType(ctx);
- } catch (NamingException e) {
- log.warn(
- "Cannot discover type of LDAP server at {},"
- + " assuming the server is RFC 2307 compliant.",
- server,
- e);
- return LdapType.RFC_2307;
- }
- }
- }
-}