Merge changes Icee61ab7,I440ef67c,I2d909950
* changes: Enable case insensitive authentication for git operations ContainerAuthFilter: fail with FORBIDDEN if username not set Enable case insensitive login to Gerrit WebUI for LDAP authentication
This commit is contained in:
@@ -298,6 +298,25 @@ then Gerrit will do the authentication (using DIGEST authentication).
|
|||||||
+
|
+
|
||||||
By default this is set to false.
|
By default this is set to false.
|
||||||
|
|
||||||
|
[[auth.userNameToLowerCase]]auth.userNameToLowerCase::
|
||||||
|
+
|
||||||
|
If set the username that is received to authenticate a git operation
|
||||||
|
is converted to lower case for looking up the user account in Gerrit.
|
||||||
|
+
|
||||||
|
By setting this parameter a case insensitive authentication for the
|
||||||
|
git operations can be achieved, if it is ensured that the usernames in
|
||||||
|
Gerrit (scheme `username`) are stored in lower case (e.g. if the
|
||||||
|
parameter link:#ldap.accountSshUserName[ldap.accountSshUserName] is
|
||||||
|
set to `${sAMAccountName.toLowerCase}`). It is important that for all
|
||||||
|
existing accounts this username is already in lower case. It is not
|
||||||
|
possible to convert the usernames of the existing accounts to lower
|
||||||
|
case because this would break the access to existing per-user
|
||||||
|
branches.
|
||||||
|
+
|
||||||
|
This parameter only affects git over http and git over SSH traffic.
|
||||||
|
+
|
||||||
|
By default this is set to false.
|
||||||
|
|
||||||
[[cache]]Section cache
|
[[cache]]Section cache
|
||||||
~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
@@ -1521,6 +1540,24 @@ Attributes such as `${dn}` or `${uidNumber}` may be useful.
|
|||||||
Default is `(memberUid=${username})` for RFC 2307,
|
Default is `(memberUid=${username})` for RFC 2307,
|
||||||
and unset (disabled) for Active Directory.
|
and unset (disabled) for Active Directory.
|
||||||
|
|
||||||
|
[[ldap.localUsernameToLowerCase]]ldap.localUsernameToLowerCase::
|
||||||
|
+
|
||||||
|
Converts the local username, that is used to login into the Gerrit
|
||||||
|
WebUI, to lower case before doing the LDAP authentication. By setting
|
||||||
|
this parameter to true, a case insensitive login to the Gerrit WebUI
|
||||||
|
can be achieved.
|
||||||
|
+
|
||||||
|
If set, it must be ensured that the local usernames for all existing
|
||||||
|
accounts are converted to lower case, otherwise a user that has a
|
||||||
|
local username that contains upper case characters cannot login
|
||||||
|
anymore. The local usernames for the existing accounts can be
|
||||||
|
converted to lower case by running the server program
|
||||||
|
link:pgm-LocalUsernamesToLowerCase.html[LocalUsernamesToLowerCase].
|
||||||
|
Please be aware that the conversion of the local usernames to lower
|
||||||
|
case can't be undone. For newly created accounts the local username
|
||||||
|
will be directly stored in lower case.
|
||||||
|
+
|
||||||
|
By default, unset/false.
|
||||||
|
|
||||||
[[mimetype]]Section mimetype
|
[[mimetype]]Section mimetype
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|||||||
68
Documentation/pgm-LocalUsernamesToLowerCase.txt
Normal file
68
Documentation/pgm-LocalUsernamesToLowerCase.txt
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
LocalUsernamesToLowerCase
|
||||||
|
=========================
|
||||||
|
|
||||||
|
NAME
|
||||||
|
----
|
||||||
|
LocalUsernamesToLowerCase - Convert the local username of every
|
||||||
|
account to lower case
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
--------
|
||||||
|
[verse]
|
||||||
|
'java' -jar gerrit.war 'LocalUsernamesToLowerCase' -d <SITE_PATH>
|
||||||
|
|
||||||
|
DESCRIPTION
|
||||||
|
-----------
|
||||||
|
Converts the local username for every account to lower case. The
|
||||||
|
local username is the username that is used to login into the Gerrit
|
||||||
|
WebUI.
|
||||||
|
|
||||||
|
This task is only intended to be run if the configuration parameter
|
||||||
|
link:config-gerrit.html#ldap.localUsernameToLowerCase[ldap.localUsernameToLowerCase]
|
||||||
|
was set to true to achieve case insensitive LDAP login to the Gerrit
|
||||||
|
WebUI.
|
||||||
|
|
||||||
|
Please be aware that the conversion of the local usernames to lower
|
||||||
|
case can't be undone.
|
||||||
|
|
||||||
|
The program will produce errors if there are accounts that have the
|
||||||
|
same local username, but with different case. In this case the local
|
||||||
|
username for these accounts is not converted to lower case.
|
||||||
|
|
||||||
|
This task can run in the background concurrently to the server if the
|
||||||
|
database is MySQL or PostgreSQL. If the database is H2, this task
|
||||||
|
must be run by itself.
|
||||||
|
|
||||||
|
OPTIONS
|
||||||
|
-------
|
||||||
|
|
||||||
|
-d::
|
||||||
|
\--site-path::
|
||||||
|
Location of the gerrit.config file, and all other per-site
|
||||||
|
configuration data, supporting libraries and log files.
|
||||||
|
|
||||||
|
\--threads::
|
||||||
|
Number of threads to perform the scan work with. Defaults to
|
||||||
|
twice the number of CPUs available.
|
||||||
|
|
||||||
|
CONTEXT
|
||||||
|
-------
|
||||||
|
This command can only be run on a server which has direct
|
||||||
|
connectivity to the metadata database.
|
||||||
|
|
||||||
|
EXAMPLES
|
||||||
|
--------
|
||||||
|
To convert the local username of every account to lower case:
|
||||||
|
|
||||||
|
====
|
||||||
|
$ java -jar gerrit.war LocalUsernamesToLowerCase -d site_path
|
||||||
|
====
|
||||||
|
|
||||||
|
See Also
|
||||||
|
--------
|
||||||
|
|
||||||
|
* Configuration parameter link:config-gerrit.html#ldap.localUsernameToLowerCase[ldap.localUsernameToLowerCase]
|
||||||
|
|
||||||
|
GERRIT
|
||||||
|
------
|
||||||
|
Part of link:index.html[Gerrit Code Review]
|
||||||
@@ -36,6 +36,9 @@ link:pgm-ExportReviewNotes.html[ExportReviewNotes]::
|
|||||||
link:pgm-ScanTrackingIds.html[ScanTrackingIds]::
|
link:pgm-ScanTrackingIds.html[ScanTrackingIds]::
|
||||||
Rescan all changes after configuring trackingids.
|
Rescan all changes after configuring trackingids.
|
||||||
|
|
||||||
|
link:pgm-LocalUsernamesToLowerCase.html[LocalUsernamesToLowerCase]::
|
||||||
|
Convert the local username of every account to lower case.
|
||||||
|
|
||||||
GERRIT
|
GERRIT
|
||||||
------
|
------
|
||||||
Part of link:index.html[Gerrit Code Review]
|
Part of link:index.html[Gerrit Code Review]
|
||||||
|
|||||||
@@ -14,17 +14,22 @@
|
|||||||
|
|
||||||
package com.google.gerrit.httpd;
|
package com.google.gerrit.httpd;
|
||||||
|
|
||||||
|
import static javax.servlet.http.HttpServletResponse.SC_FORBIDDEN;
|
||||||
import static javax.servlet.http.HttpServletResponse.SC_UNAUTHORIZED;
|
import static javax.servlet.http.HttpServletResponse.SC_UNAUTHORIZED;
|
||||||
|
|
||||||
import com.google.gerrit.server.account.AccountCache;
|
import com.google.gerrit.server.account.AccountCache;
|
||||||
import com.google.gerrit.server.account.AccountState;
|
import com.google.gerrit.server.account.AccountState;
|
||||||
import com.google.gerrit.server.config.AuthConfig;
|
import com.google.gerrit.server.config.AuthConfig;
|
||||||
|
import com.google.gerrit.server.config.GerritServerConfig;
|
||||||
import com.google.gwtjsonrpc.server.XsrfException;
|
import com.google.gwtjsonrpc.server.XsrfException;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import com.google.inject.Provider;
|
import com.google.inject.Provider;
|
||||||
import com.google.inject.Singleton;
|
import com.google.inject.Singleton;
|
||||||
|
|
||||||
|
import org.eclipse.jgit.lib.Config;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
import javax.servlet.Filter;
|
import javax.servlet.Filter;
|
||||||
import javax.servlet.FilterChain;
|
import javax.servlet.FilterChain;
|
||||||
@@ -53,12 +58,14 @@ class ContainerAuthFilter implements Filter {
|
|||||||
|
|
||||||
private final Provider<WebSession> session;
|
private final Provider<WebSession> session;
|
||||||
private final AccountCache accountCache;
|
private final AccountCache accountCache;
|
||||||
|
private final Config config;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
ContainerAuthFilter(Provider<WebSession> session, AccountCache accountCache)
|
ContainerAuthFilter(Provider<WebSession> session, AccountCache accountCache,
|
||||||
throws XsrfException {
|
@GerritServerConfig Config config) throws XsrfException {
|
||||||
this.session = session;
|
this.session = session;
|
||||||
this.accountCache = accountCache;
|
this.accountCache = accountCache;
|
||||||
|
this.config = config;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -83,9 +90,15 @@ class ContainerAuthFilter implements Filter {
|
|||||||
|
|
||||||
private boolean verify(HttpServletRequest req, HttpServletResponseWrapper rsp)
|
private boolean verify(HttpServletRequest req, HttpServletResponseWrapper rsp)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
final String username = req.getRemoteUser();
|
String username = req.getRemoteUser();
|
||||||
final AccountState who =
|
if (username == null) {
|
||||||
(username == null) ? null : accountCache.getByUsername(username);
|
rsp.sendError(SC_FORBIDDEN);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (config.getBoolean("auth", "userNameToLowerCase", false)) {
|
||||||
|
username = username.toLowerCase(Locale.US);
|
||||||
|
}
|
||||||
|
final AccountState who = accountCache.getByUsername(username);
|
||||||
if (who == null || !who.getAccount().isActive()) {
|
if (who == null || !who.getAccount().isActive()) {
|
||||||
rsp.sendError(SC_UNAUTHORIZED);
|
rsp.sendError(SC_UNAUTHORIZED);
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -23,18 +23,22 @@ import static javax.servlet.http.HttpServletResponse.SC_UNAUTHORIZED;
|
|||||||
import com.google.gerrit.server.account.AccountCache;
|
import com.google.gerrit.server.account.AccountCache;
|
||||||
import com.google.gerrit.server.account.AccountState;
|
import com.google.gerrit.server.account.AccountState;
|
||||||
import com.google.gerrit.server.config.CanonicalWebUrl;
|
import com.google.gerrit.server.config.CanonicalWebUrl;
|
||||||
|
import com.google.gerrit.server.config.GerritServerConfig;
|
||||||
import com.google.gwtjsonrpc.server.SignedToken;
|
import com.google.gwtjsonrpc.server.SignedToken;
|
||||||
import com.google.gwtjsonrpc.server.XsrfException;
|
import com.google.gwtjsonrpc.server.XsrfException;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import com.google.inject.Provider;
|
import com.google.inject.Provider;
|
||||||
import com.google.inject.Singleton;
|
import com.google.inject.Singleton;
|
||||||
|
|
||||||
|
import org.eclipse.jgit.lib.Config;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.security.MessageDigest;
|
import java.security.MessageDigest;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
@@ -67,16 +71,18 @@ class ProjectDigestFilter implements Filter {
|
|||||||
private final Provider<String> urlProvider;
|
private final Provider<String> urlProvider;
|
||||||
private final Provider<WebSession> session;
|
private final Provider<WebSession> session;
|
||||||
private final AccountCache accountCache;
|
private final AccountCache accountCache;
|
||||||
|
private final Config config;
|
||||||
private final SignedToken tokens;
|
private final SignedToken tokens;
|
||||||
private ServletContext context;
|
private ServletContext context;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
ProjectDigestFilter(@CanonicalWebUrl @Nullable Provider<String> urlProvider,
|
ProjectDigestFilter(@CanonicalWebUrl @Nullable Provider<String> urlProvider,
|
||||||
Provider<WebSession> session, AccountCache accountCache)
|
Provider<WebSession> session, AccountCache accountCache,
|
||||||
throws XsrfException {
|
@GerritServerConfig Config config) throws XsrfException {
|
||||||
this.urlProvider = urlProvider;
|
this.urlProvider = urlProvider;
|
||||||
this.session = session;
|
this.session = session;
|
||||||
this.accountCache = accountCache;
|
this.accountCache = accountCache;
|
||||||
|
this.config = config;
|
||||||
this.tokens = new SignedToken((int) SECONDS.convert(1, HOURS));
|
this.tokens = new SignedToken((int) SECONDS.convert(1, HOURS));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,7 +117,7 @@ class ProjectDigestFilter implements Filter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final Map<String, String> p = parseAuthorization(hdr);
|
final Map<String, String> p = parseAuthorization(hdr);
|
||||||
final String username = p.get("username");
|
final String user = p.get("username");
|
||||||
final String realm = p.get("realm");
|
final String realm = p.get("realm");
|
||||||
final String nonce = p.get("nonce");
|
final String nonce = p.get("nonce");
|
||||||
final String uri = p.get("uri");
|
final String uri = p.get("uri");
|
||||||
@@ -121,7 +127,7 @@ class ProjectDigestFilter implements Filter {
|
|||||||
final String cnonce = p.get("cnonce");
|
final String cnonce = p.get("cnonce");
|
||||||
final String method = req.getMethod();
|
final String method = req.getMethod();
|
||||||
|
|
||||||
if (username == null //
|
if (user == null //
|
||||||
|| realm == null //
|
|| realm == null //
|
||||||
|| nonce == null //
|
|| nonce == null //
|
||||||
|| uri == null //
|
|| uri == null //
|
||||||
@@ -133,6 +139,11 @@ class ProjectDigestFilter implements Filter {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String username = user;
|
||||||
|
if (config.getBoolean("auth", "userNameToLowerCase", false)) {
|
||||||
|
username = username.toLowerCase(Locale.US);
|
||||||
|
}
|
||||||
|
|
||||||
final AccountState who = accountCache.getByUsername(username);
|
final AccountState who = accountCache.getByUsername(username);
|
||||||
if (who == null || ! who.getAccount().isActive()) {
|
if (who == null || ! who.getAccount().isActive()) {
|
||||||
rsp.sendError(SC_UNAUTHORIZED);
|
rsp.sendError(SC_UNAUTHORIZED);
|
||||||
@@ -145,7 +156,7 @@ class ProjectDigestFilter implements Filter {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
final String A1 = username + ":" + realm + ":" + passwd;
|
final String A1 = user + ":" + realm + ":" + passwd;
|
||||||
final String A2 = method + ":" + uri;
|
final String A2 = method + ":" + uri;
|
||||||
final String expect =
|
final String expect =
|
||||||
KD(H(A1), nonce + ":" + nc + ":" + cnonce + ":" + qop + ":" + H(A2));
|
KD(H(A1), nonce + ":" + nc + ":" + cnonce + ":" + qop + ":" + H(A2));
|
||||||
|
|||||||
@@ -0,0 +1,145 @@
|
|||||||
|
// Copyright (C) 2011 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.pgm;
|
||||||
|
|
||||||
|
import static com.google.gerrit.server.schema.DataSourceProvider.Context.MULTI_USER;
|
||||||
|
|
||||||
|
import com.google.gerrit.lifecycle.LifecycleManager;
|
||||||
|
import com.google.gerrit.pgm.util.SiteProgram;
|
||||||
|
import com.google.gerrit.reviewdb.AccountExternalId;
|
||||||
|
import com.google.gerrit.reviewdb.ReviewDb;
|
||||||
|
import com.google.gerrit.server.schema.SchemaVersionCheck;
|
||||||
|
import com.google.gwtorm.client.OrmException;
|
||||||
|
import com.google.gwtorm.client.SchemaFactory;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import com.google.inject.Injector;
|
||||||
|
|
||||||
|
import org.eclipse.jgit.lib.TextProgressMonitor;
|
||||||
|
import org.kohsuke.args4j.Option;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
/** Converts the local username for all accounts to lower case */
|
||||||
|
public class LocalUsernamesToLowerCase extends SiteProgram {
|
||||||
|
@Option(name = "--threads", usage = "Number of concurrent threads to run")
|
||||||
|
private int threads = 2;
|
||||||
|
|
||||||
|
private final LifecycleManager manager = new LifecycleManager();
|
||||||
|
private final TextProgressMonitor monitor = new TextProgressMonitor();
|
||||||
|
private List<AccountExternalId> todo;
|
||||||
|
|
||||||
|
private Injector dbInjector;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private SchemaFactory<ReviewDb> database;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int run() throws Exception {
|
||||||
|
if (threads <= 0) {
|
||||||
|
threads = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
dbInjector = createDbInjector(MULTI_USER);
|
||||||
|
manager.add(dbInjector,
|
||||||
|
dbInjector.createChildInjector(SchemaVersionCheck.module()));
|
||||||
|
manager.start();
|
||||||
|
dbInjector.injectMembers(this);
|
||||||
|
|
||||||
|
final ReviewDb db = database.open();
|
||||||
|
try {
|
||||||
|
todo = db.accountExternalIds().all().toList();
|
||||||
|
synchronized (monitor) {
|
||||||
|
monitor.beginTask("Converting local username", todo.size());
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
db.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
final List<Worker> workers = new ArrayList<Worker>(threads);
|
||||||
|
for (int tid = 0; tid < threads; tid++) {
|
||||||
|
Worker t = new Worker();
|
||||||
|
t.start();
|
||||||
|
workers.add(t);
|
||||||
|
}
|
||||||
|
for (Worker t : workers) {
|
||||||
|
t.join();
|
||||||
|
}
|
||||||
|
synchronized (monitor) {
|
||||||
|
monitor.endTask();
|
||||||
|
}
|
||||||
|
manager.stop();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void convertLocalUserToLowerCase(final ReviewDb db,
|
||||||
|
final AccountExternalId extId) {
|
||||||
|
if (extId.isScheme(AccountExternalId.SCHEME_GERRIT)) {
|
||||||
|
final String localUser = extId.getSchemeRest();
|
||||||
|
final String localUserLowerCase = localUser.toLowerCase(Locale.US);
|
||||||
|
if (!localUser.equals(localUserLowerCase)) {
|
||||||
|
final AccountExternalId.Key extIdKeyLowerCase =
|
||||||
|
new AccountExternalId.Key(AccountExternalId.SCHEME_GERRIT,
|
||||||
|
localUserLowerCase);
|
||||||
|
final AccountExternalId extIdLowerCase =
|
||||||
|
new AccountExternalId(extId.getAccountId(), extIdKeyLowerCase);
|
||||||
|
try {
|
||||||
|
db.accountExternalIds().insert(Collections.singleton(extIdLowerCase));
|
||||||
|
db.accountExternalIds().delete(Collections.singleton(extId));
|
||||||
|
} catch (OrmException error) {
|
||||||
|
System.err.println("ERR " + error.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private AccountExternalId next() {
|
||||||
|
synchronized (todo) {
|
||||||
|
if (todo.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return todo.remove(todo.size() - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class Worker extends Thread {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
final ReviewDb db;
|
||||||
|
try {
|
||||||
|
db = database.open();
|
||||||
|
} catch (OrmException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
for (;;) {
|
||||||
|
final AccountExternalId extId = next();
|
||||||
|
if (extId == null) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
convertLocalUserToLowerCase(db, extId);
|
||||||
|
synchronized (monitor) {
|
||||||
|
monitor.update(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
db.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -42,4 +42,7 @@ public interface AccountExternalIdAccess extends
|
|||||||
@Query("WHERE emailAddress >= ? AND emailAddress <= ? ORDER BY emailAddress LIMIT ?")
|
@Query("WHERE emailAddress >= ? AND emailAddress <= ? ORDER BY emailAddress LIMIT ?")
|
||||||
ResultSet<AccountExternalId> suggestByEmailAddress(String emailA,
|
ResultSet<AccountExternalId> suggestByEmailAddress(String emailA,
|
||||||
String emailB, int limit) throws OrmException;
|
String emailB, int limit) throws OrmException;
|
||||||
|
|
||||||
|
@Query
|
||||||
|
ResultSet<AccountExternalId> all() throws OrmException;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ public class AuthRequest {
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
private final String externalId;
|
private String externalId;
|
||||||
private String password;
|
private String password;
|
||||||
private String displayName;
|
private String displayName;
|
||||||
private String emailAddress;
|
private String emailAddress;
|
||||||
@@ -78,6 +78,14 @@ public class AuthRequest {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setLocalUser(final String localUser) {
|
||||||
|
if (isScheme(SCHEME_GERRIT)) {
|
||||||
|
final AccountExternalId.Key key =
|
||||||
|
new AccountExternalId.Key(SCHEME_GERRIT, localUser);
|
||||||
|
externalId = key.get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public String getPassword() {
|
public String getPassword() {
|
||||||
return password;
|
return password;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ import java.util.Collections;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
@@ -67,6 +68,7 @@ class LdapRealm implements Realm {
|
|||||||
private final EmailExpander emailExpander;
|
private final EmailExpander emailExpander;
|
||||||
private final Cache<String, Account.Id> usernameCache;
|
private final Cache<String, Account.Id> usernameCache;
|
||||||
private final Set<Account.FieldName> readOnlyAccountFields;
|
private final Set<Account.FieldName> readOnlyAccountFields;
|
||||||
|
private final Config config;
|
||||||
|
|
||||||
private final Cache<String, Set<AccountGroup.UUID>> membershipCache;
|
private final Cache<String, Set<AccountGroup.UUID>> membershipCache;
|
||||||
|
|
||||||
@@ -83,6 +85,7 @@ class LdapRealm implements Realm {
|
|||||||
this.emailExpander = emailExpander;
|
this.emailExpander = emailExpander;
|
||||||
this.usernameCache = usernameCache;
|
this.usernameCache = usernameCache;
|
||||||
this.membershipCache = membershipCache;
|
this.membershipCache = membershipCache;
|
||||||
|
this.config = config;
|
||||||
|
|
||||||
this.readOnlyAccountFields = new HashSet<Account.FieldName>();
|
this.readOnlyAccountFields = new HashSet<Account.FieldName>();
|
||||||
|
|
||||||
@@ -181,6 +184,10 @@ class LdapRealm implements Realm {
|
|||||||
|
|
||||||
public AuthRequest authenticate(final AuthRequest who)
|
public AuthRequest authenticate(final AuthRequest who)
|
||||||
throws AccountException {
|
throws AccountException {
|
||||||
|
if (config.getBoolean("ldap", "localUsernameToLowerCase", false)) {
|
||||||
|
who.setLocalUser(who.getLocalUser().toLowerCase(Locale.US));
|
||||||
|
}
|
||||||
|
|
||||||
final String username = who.getLocalUser();
|
final String username = who.getLocalUser();
|
||||||
try {
|
try {
|
||||||
final DirContext ctx;
|
final DirContext ctx;
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import com.google.gerrit.server.AccessPath;
|
|||||||
import com.google.gerrit.server.CurrentUser;
|
import com.google.gerrit.server.CurrentUser;
|
||||||
import com.google.gerrit.server.IdentifiedUser;
|
import com.google.gerrit.server.IdentifiedUser;
|
||||||
import com.google.gerrit.server.PeerDaemonUser;
|
import com.google.gerrit.server.PeerDaemonUser;
|
||||||
|
import com.google.gerrit.server.config.GerritServerConfig;
|
||||||
import com.google.gerrit.server.config.SitePaths;
|
import com.google.gerrit.server.config.SitePaths;
|
||||||
import com.google.gerrit.sshd.SshScope.Context;
|
import com.google.gerrit.sshd.SshScope.Context;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
@@ -33,6 +34,7 @@ import org.apache.sshd.common.SshException;
|
|||||||
import org.apache.sshd.common.util.Buffer;
|
import org.apache.sshd.common.util.Buffer;
|
||||||
import org.apache.sshd.server.PublickeyAuthenticator;
|
import org.apache.sshd.server.PublickeyAuthenticator;
|
||||||
import org.apache.sshd.server.session.ServerSession;
|
import org.apache.sshd.server.session.ServerSession;
|
||||||
|
import org.eclipse.jgit.lib.Config;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
@@ -47,6 +49,7 @@ import java.security.PublicKey;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.Locale;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -61,17 +64,20 @@ class DatabasePubKeyAuth implements PublickeyAuthenticator {
|
|||||||
private final SshLog sshLog;
|
private final SshLog sshLog;
|
||||||
private final IdentifiedUser.GenericFactory userFactory;
|
private final IdentifiedUser.GenericFactory userFactory;
|
||||||
private final PeerDaemonUser.Factory peerFactory;
|
private final PeerDaemonUser.Factory peerFactory;
|
||||||
|
private final Config config;
|
||||||
private final Set<PublicKey> myHostKeys;
|
private final Set<PublicKey> myHostKeys;
|
||||||
private volatile PeerKeyCache peerKeyCache;
|
private volatile PeerKeyCache peerKeyCache;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
DatabasePubKeyAuth(final SshKeyCacheImpl skc, final SshLog l,
|
DatabasePubKeyAuth(final SshKeyCacheImpl skc, final SshLog l,
|
||||||
final IdentifiedUser.GenericFactory uf, final PeerDaemonUser.Factory pf,
|
final IdentifiedUser.GenericFactory uf, final PeerDaemonUser.Factory pf,
|
||||||
final SitePaths site, final KeyPairProvider hostKeyProvider) {
|
final SitePaths site, final KeyPairProvider hostKeyProvider,
|
||||||
|
final @GerritServerConfig Config cfg) {
|
||||||
sshKeyCache = skc;
|
sshKeyCache = skc;
|
||||||
sshLog = l;
|
sshLog = l;
|
||||||
userFactory = uf;
|
userFactory = uf;
|
||||||
peerFactory = pf;
|
peerFactory = pf;
|
||||||
|
config = cfg;
|
||||||
myHostKeys = myHostKeys(hostKeyProvider);
|
myHostKeys = myHostKeys(hostKeyProvider);
|
||||||
peerKeyCache = new PeerKeyCache(site.peer_keys);
|
peerKeyCache = new PeerKeyCache(site.peer_keys);
|
||||||
}
|
}
|
||||||
@@ -91,7 +97,7 @@ class DatabasePubKeyAuth implements PublickeyAuthenticator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean authenticate(final String username,
|
public boolean authenticate(String username,
|
||||||
final PublicKey suppliedKey, final ServerSession session) {
|
final PublicKey suppliedKey, final ServerSession session) {
|
||||||
final SshSession sd = session.getAttribute(SshSession.KEY);
|
final SshSession sd = session.getAttribute(SshSession.KEY);
|
||||||
|
|
||||||
@@ -107,6 +113,10 @@ class DatabasePubKeyAuth implements PublickeyAuthenticator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (config.getBoolean("auth", "userNameToLowerCase", false)) {
|
||||||
|
username = username.toLowerCase(Locale.US);
|
||||||
|
}
|
||||||
|
|
||||||
final Iterable<SshKeyCacheEntry> keyList = sshKeyCache.get(username);
|
final Iterable<SshKeyCacheEntry> keyList = sshKeyCache.get(username);
|
||||||
final SshKeyCacheEntry key = find(keyList, suppliedKey);
|
final SshKeyCacheEntry key = find(keyList, suppliedKey);
|
||||||
if (key == null) {
|
if (key == null) {
|
||||||
|
|||||||
Reference in New Issue
Block a user