Line data Source code
1 : // Copyright (C) 2012 The Android Open Source Project 2 : // 3 : // Licensed under the Apache License, Version 2.0 (the "License"); 4 : // you may not use this file except in compliance with the License. 5 : // You may obtain a copy of the License at 6 : // 7 : // http://www.apache.org/licenses/LICENSE-2.0 8 : // 9 : // Unless required by applicable law or agreed to in writing, software 10 : // distributed under the License is distributed on an "AS IS" BASIS, 11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 : // See the License for the specific language governing permissions and 13 : // limitations under the License. 14 : 15 : package com.google.gerrit.auth.ldap; 16 : 17 : import com.google.common.flogger.FluentLogger; 18 : import com.google.gerrit.extensions.client.AuthType; 19 : import com.google.gerrit.server.account.AccountException; 20 : import com.google.gerrit.server.auth.AuthBackend; 21 : import com.google.gerrit.server.auth.AuthException; 22 : import com.google.gerrit.server.auth.AuthRequest; 23 : import com.google.gerrit.server.auth.AuthUser; 24 : import com.google.gerrit.server.auth.InvalidCredentialsException; 25 : import com.google.gerrit.server.auth.MissingCredentialsException; 26 : import com.google.gerrit.server.auth.UnknownUserException; 27 : import com.google.gerrit.server.auth.UserNotAllowedException; 28 : import com.google.gerrit.server.config.AuthConfig; 29 : import com.google.gerrit.server.config.GerritServerConfig; 30 : import com.google.inject.Inject; 31 : import java.io.IOException; 32 : import java.util.Locale; 33 : import javax.naming.NamingException; 34 : import javax.naming.directory.DirContext; 35 : import javax.security.auth.login.LoginException; 36 : import org.eclipse.jgit.lib.Config; 37 : 38 : /** Implementation of AuthBackend for the LDAP authentication system. */ 39 : public class LdapAuthBackend implements AuthBackend { 40 0 : private static final FluentLogger logger = FluentLogger.forEnclosingClass(); 41 : 42 : private final Helper helper; 43 : private final AuthConfig authConfig; 44 : private final boolean lowerCaseUsername; 45 : 46 : @Inject 47 0 : public LdapAuthBackend(Helper helper, AuthConfig authConfig, @GerritServerConfig Config config) { 48 0 : this.helper = helper; 49 0 : this.authConfig = authConfig; 50 0 : this.lowerCaseUsername = config.getBoolean("ldap", "localUsernameToLowerCase", false); 51 0 : } 52 : 53 : @Override 54 : public String getDomain() { 55 0 : return "ldap"; 56 : } 57 : 58 : @Override 59 : public AuthUser authenticate(AuthRequest req) 60 : throws MissingCredentialsException, InvalidCredentialsException, UnknownUserException, 61 : UserNotAllowedException, AuthException { 62 0 : if (!req.getUsername().isPresent() || !req.getPassword().isPresent()) { 63 0 : throw new MissingCredentialsException(); 64 : } 65 : 66 : String username = 67 0 : lowerCaseUsername 68 0 : ? req.getUsername().map(u -> u.toLowerCase(Locale.US)).get() 69 0 : : req.getUsername().get(); 70 : try { 71 : final DirContext ctx; 72 0 : if (authConfig.getAuthType() == AuthType.LDAP_BIND) { 73 0 : ctx = helper.authenticate(username, req.getPassword().get()); 74 : } else { 75 0 : ctx = helper.open(); 76 : } 77 : try { 78 0 : final Helper.LdapSchema schema = helper.getSchema(ctx); 79 0 : final LdapQuery.Result m = helper.findAccount(schema, ctx, username, false); 80 : 81 0 : if (authConfig.getAuthType() == AuthType.LDAP) { 82 : // We found the user account, but we need to verify 83 : // the password matches it before we can continue. 84 : // 85 0 : helper.close(helper.authenticate(m.getDN(), req.getPassword().get())); 86 : } 87 0 : return new AuthUser(AuthUser.UUID.create(username), username); 88 : } finally { 89 0 : helper.close(ctx); 90 : } 91 0 : } catch (AccountException e) { 92 0 : logger.atSevere().withCause(e).log("Cannot query LDAP to authenticate user"); 93 0 : throw new InvalidCredentialsException("Cannot query LDAP for account", e); 94 0 : } catch (IOException | NamingException e) { 95 0 : logger.atSevere().withCause(e).log("Cannot query LDAP to authenticate user"); 96 0 : throw new AuthException("Cannot query LDAP for account", e); 97 0 : } catch (LoginException e) { 98 0 : logger.atSevere().withCause(e).log("Cannot authenticate server via JAAS"); 99 0 : throw new AuthException("Cannot query LDAP for account", e); 100 : } 101 : } 102 : }