Enable specific AccessPaths based on authentication
If the authentication method permits an AccessPath, add it to the WebSession as a permitted path. Downstream from authentication a CurrentUser can change its access path based on the entry point of the request, allowing RefControl to make decisions around this as expected, without running into the race condition of making user before the real access method can be determined. This allows authentication systems to decide on their own if the REST_API was sufficiently protected from a potentially evil script. Change-Id: Iefbe6745421f5f438bc06e2e4578a7207718b9a5
This commit is contained in:
@@ -35,6 +35,8 @@ import com.google.inject.servlet.RequestScoped;
|
|||||||
|
|
||||||
import org.eclipse.jgit.http.server.GitSmartHttpTools;
|
import org.eclipse.jgit.http.server.GitSmartHttpTools;
|
||||||
|
|
||||||
|
import java.util.EnumSet;
|
||||||
|
|
||||||
import javax.servlet.http.Cookie;
|
import javax.servlet.http.Cookie;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
@@ -66,7 +68,7 @@ public final class CacheBasedWebSession implements WebSession {
|
|||||||
private final AuthConfig authConfig;
|
private final AuthConfig authConfig;
|
||||||
private final Provider<AnonymousUser> anonymousProvider;
|
private final Provider<AnonymousUser> anonymousProvider;
|
||||||
private final IdentifiedUser.RequestFactory identified;
|
private final IdentifiedUser.RequestFactory identified;
|
||||||
private AccessPath accessPath;
|
private final EnumSet<AccessPath> okPaths = EnumSet.of(AccessPath.UNKNOWN);
|
||||||
private Cookie outCookie;
|
private Cookie outCookie;
|
||||||
|
|
||||||
private Key key;
|
private Key key;
|
||||||
@@ -85,36 +87,31 @@ public final class CacheBasedWebSession implements WebSession {
|
|||||||
this.anonymousProvider = anonymousProvider;
|
this.anonymousProvider = anonymousProvider;
|
||||||
this.identified = identified;
|
this.identified = identified;
|
||||||
|
|
||||||
String cookie = request.getHeader("Authorization");
|
if (!GitSmartHttpTools.isGitClient(request)) {
|
||||||
if (cookie != null && cookie.startsWith("Bearer ")) {
|
String cookie = readCookie();
|
||||||
cookie = cookie.substring("Bearer ".length());
|
String token = request.getHeader("Authorization");
|
||||||
accessPath = AccessPath.REST_API;
|
if (token != null && token.startsWith("Bearer ")) {
|
||||||
} else if (cookie != null && GitSmartHttpTools.isGitClient(request)) {
|
token = token.substring("Bearer ".length());
|
||||||
accessPath = AccessPath.GIT;
|
okPaths.add(AccessPath.REST_API);
|
||||||
} else {
|
} else {
|
||||||
cookie = readCookie();
|
token = cookie;
|
||||||
accessPath = AccessPath.WEB_BROWSER;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cookie != null) {
|
if (token != null) {
|
||||||
key = new Key(cookie);
|
key = new Key(token);
|
||||||
val = manager.get(key);
|
val = manager.get(key);
|
||||||
} else {
|
|
||||||
key = null;
|
|
||||||
val = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isSignedIn() && val.needsCookieRefresh()) {
|
if (isSignedIn() && val.needsCookieRefresh()) {
|
||||||
// Cookie is more than half old. Send the cookie again to the
|
// Cookie is more than half old. Send the cookie again to the
|
||||||
// client with an updated expiration date. We don't dare to
|
// client with an updated expiration date.
|
||||||
// change the key token here because there may be other RPCs
|
|
||||||
// queued up in the browser whose xsrfKey would not get updated
|
|
||||||
// with the new token, causing them to fail.
|
|
||||||
//
|
|
||||||
val = manager.createVal(key, val);
|
val = manager.createVal(key, val);
|
||||||
|
if (cookie != null) {
|
||||||
saveCookie();
|
saveCookie();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private String readCookie() {
|
private String readCookie() {
|
||||||
final Cookie[] all = request.getCookies();
|
final Cookie[] all = request.getCookies();
|
||||||
@@ -129,10 +126,12 @@ public final class CacheBasedWebSession implements WebSession {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean isSignedIn() {
|
public boolean isSignedIn() {
|
||||||
return val != null;
|
return val != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public String getAuthorization() {
|
public String getAuthorization() {
|
||||||
return isSignedIn() ? "Bearer " + key.getToken() : null;
|
return isSignedIn() ? "Bearer " + key.getToken() : null;
|
||||||
}
|
}
|
||||||
@@ -142,17 +141,34 @@ public final class CacheBasedWebSession implements WebSession {
|
|||||||
return keyIn.equals(getAuthorization());
|
return keyIn.equals(getAuthorization());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAccessPathOk(AccessPath path) {
|
||||||
|
return okPaths.contains(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setAccessPathOk(AccessPath path, boolean ok) {
|
||||||
|
if (ok) {
|
||||||
|
okPaths.add(path);
|
||||||
|
} else {
|
||||||
|
okPaths.remove(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public AccountExternalId.Key getLastLoginExternalId() {
|
public AccountExternalId.Key getLastLoginExternalId() {
|
||||||
return val != null ? val.getExternalId() : null;
|
return val != null ? val.getExternalId() : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public CurrentUser getCurrentUser() {
|
public CurrentUser getCurrentUser() {
|
||||||
if (isSignedIn()) {
|
if (isSignedIn()) {
|
||||||
return identified.create(accessPath, val.getAccountId());
|
return identified.create(val.getAccountId());
|
||||||
}
|
}
|
||||||
return anonymousProvider.get();
|
return anonymousProvider.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void login(final AuthResult res, final boolean rememberMe) {
|
public void login(final AuthResult res, final boolean rememberMe) {
|
||||||
final Account.Id id = res.getAccountId();
|
final Account.Id id = res.getAccountId();
|
||||||
final AccountExternalId.Key identity = res.getExternalId();
|
final AccountExternalId.Key identity = res.getExternalId();
|
||||||
@@ -167,11 +183,13 @@ public final class CacheBasedWebSession implements WebSession {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Set the user account for this current request only. */
|
/** Set the user account for this current request only. */
|
||||||
|
@Override
|
||||||
public void setUserAccountId(Account.Id id) {
|
public void setUserAccountId(Account.Id id) {
|
||||||
key = new Key("id:" + id);
|
key = new Key("id:" + id);
|
||||||
val = new Val(id, 0, false, null, 0, null);
|
val = new Val(id, 0, false, null, 0, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void logout() {
|
public void logout() {
|
||||||
if (val != null) {
|
if (val != null) {
|
||||||
manager.destroy(key);
|
manager.destroy(key);
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ package com.google.gerrit.httpd;
|
|||||||
import static javax.servlet.http.HttpServletResponse.SC_FORBIDDEN;
|
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.AccessPath;
|
||||||
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.GerritServerConfig;
|
import com.google.gerrit.server.config.GerritServerConfig;
|
||||||
@@ -99,7 +100,10 @@ class ContainerAuthFilter implements Filter {
|
|||||||
rsp.sendError(SC_UNAUTHORIZED);
|
rsp.sendError(SC_UNAUTHORIZED);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
session.get().setUserAccountId(who.getAccount().getId());
|
WebSession ws = session.get();
|
||||||
|
ws.setUserAccountId(who.getAccount().getId());
|
||||||
|
ws.setAccessPathOk(AccessPath.GIT, true);
|
||||||
|
ws.setAccessPathOk(AccessPath.REST_API, true);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,9 @@ import com.google.common.cache.Cache;
|
|||||||
import com.google.gerrit.common.data.Capable;
|
import com.google.gerrit.common.data.Capable;
|
||||||
import com.google.gerrit.reviewdb.client.Project;
|
import com.google.gerrit.reviewdb.client.Project;
|
||||||
import com.google.gerrit.reviewdb.server.ReviewDb;
|
import com.google.gerrit.reviewdb.server.ReviewDb;
|
||||||
|
import com.google.gerrit.server.AccessPath;
|
||||||
import com.google.gerrit.server.AnonymousUser;
|
import com.google.gerrit.server.AnonymousUser;
|
||||||
|
import com.google.gerrit.server.CurrentUser;
|
||||||
import com.google.gerrit.server.IdentifiedUser;
|
import com.google.gerrit.server.IdentifiedUser;
|
||||||
import com.google.gerrit.server.cache.CacheModule;
|
import com.google.gerrit.server.cache.CacheModule;
|
||||||
import com.google.gerrit.server.git.AsyncReceiveCommits;
|
import com.google.gerrit.server.git.AsyncReceiveCommits;
|
||||||
@@ -157,8 +159,12 @@ public class GitOverHttpServlet extends GitServlet {
|
|||||||
} catch (NoSuchProjectException err) {
|
} catch (NoSuchProjectException err) {
|
||||||
throw new RepositoryNotFoundException(projectName);
|
throw new RepositoryNotFoundException(projectName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CurrentUser user = pc.getCurrentUser();
|
||||||
|
user.setAccessPath(AccessPath.GIT);
|
||||||
|
|
||||||
if (!pc.isVisible()) {
|
if (!pc.isVisible()) {
|
||||||
if (pc.getCurrentUser() instanceof AnonymousUser) {
|
if (user instanceof AnonymousUser) {
|
||||||
throw new ServiceNotAuthorizedException();
|
throw new ServiceNotAuthorizedException();
|
||||||
} else {
|
} else {
|
||||||
throw new ServiceNotEnabledException();
|
throw new ServiceNotEnabledException();
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import static javax.servlet.http.HttpServletResponse.SC_UNAUTHORIZED;
|
|||||||
|
|
||||||
import com.google.common.base.Objects;
|
import com.google.common.base.Objects;
|
||||||
import com.google.common.base.Strings;
|
import com.google.common.base.Strings;
|
||||||
|
import com.google.gerrit.server.AccessPath;
|
||||||
import com.google.gerrit.server.account.AccountCache;
|
import com.google.gerrit.server.account.AccountCache;
|
||||||
import com.google.gerrit.server.account.AccountException;
|
import com.google.gerrit.server.account.AccountException;
|
||||||
import com.google.gerrit.server.account.AccountManager;
|
import com.google.gerrit.server.account.AccountManager;
|
||||||
@@ -103,10 +104,9 @@ class ProjectBasicAuthFilter implements Filter {
|
|||||||
private boolean verify(HttpServletRequest req, Response rsp)
|
private boolean verify(HttpServletRequest req, Response rsp)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
final String hdr = req.getHeader(AUTHORIZATION);
|
final String hdr = req.getHeader(AUTHORIZATION);
|
||||||
if (hdr == null) {
|
if (hdr == null || !hdr.startsWith(LIT_BASIC)) {
|
||||||
// Allow an anonymous connection through, or it might be using a
|
// Allow an anonymous connection through, or it might be using a
|
||||||
// session cookie instead of basic authentication.
|
// session cookie instead of basic authentication.
|
||||||
//
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -142,7 +142,10 @@ class ProjectBasicAuthFilter implements Filter {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
AuthResult whoAuthResult = accountManager.authenticate(whoAuth);
|
AuthResult whoAuthResult = accountManager.authenticate(whoAuth);
|
||||||
session.get().setUserAccountId(whoAuthResult.getAccountId());
|
WebSession ws = session.get();
|
||||||
|
ws.setUserAccountId(whoAuthResult.getAccountId());
|
||||||
|
ws.setAccessPathOk(AccessPath.GIT, true);
|
||||||
|
ws.setAccessPathOk(AccessPath.REST_API, true);
|
||||||
return true;
|
return true;
|
||||||
} catch (AccountException e) {
|
} catch (AccountException e) {
|
||||||
log.warn("Authentication failed for " + username, e);
|
log.warn("Authentication failed for " + username, e);
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import static javax.servlet.http.HttpServletResponse.SC_FORBIDDEN;
|
|||||||
import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
|
import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
|
||||||
import static javax.servlet.http.HttpServletResponse.SC_UNAUTHORIZED;
|
import static javax.servlet.http.HttpServletResponse.SC_UNAUTHORIZED;
|
||||||
|
|
||||||
|
import com.google.gerrit.server.AccessPath;
|
||||||
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;
|
||||||
@@ -109,10 +110,9 @@ class ProjectDigestFilter implements Filter {
|
|||||||
private boolean verify(HttpServletRequest req, Response rsp)
|
private boolean verify(HttpServletRequest req, Response rsp)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
final String hdr = req.getHeader(AUTHORIZATION);
|
final String hdr = req.getHeader(AUTHORIZATION);
|
||||||
if (hdr == null) {
|
if (hdr == null || !hdr.startsWith("Digest ")) {
|
||||||
// Allow an anonymous connection through, or it might be using a
|
// Allow an anonymous connection through, or it might be using a
|
||||||
// session cookie instead of digest authentication.
|
// session cookie instead of digest authentication.
|
||||||
//
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,7 +164,10 @@ class ProjectDigestFilter implements Filter {
|
|||||||
if (expect.equals(response)) {
|
if (expect.equals(response)) {
|
||||||
try {
|
try {
|
||||||
if (tokens.checkToken(nonce, "") != null) {
|
if (tokens.checkToken(nonce, "") != null) {
|
||||||
session.get().setUserAccountId(who.getAccount().getId());
|
WebSession ws = session.get();
|
||||||
|
ws.setUserAccountId(who.getAccount().getId());
|
||||||
|
ws.setAccessPathOk(AccessPath.GIT, true);
|
||||||
|
ws.setAccessPathOk(AccessPath.REST_API, true);
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@@ -229,12 +232,6 @@ class ProjectDigestFilter implements Filter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Map<String, String> parseAuthorization(String auth) {
|
private Map<String, String> parseAuthorization(String auth) {
|
||||||
if (!auth.startsWith("Digest ")) {
|
|
||||||
// We only support Digest authentication scheme, deny the rest.
|
|
||||||
//
|
|
||||||
return Collections.emptyMap();
|
|
||||||
}
|
|
||||||
|
|
||||||
Map<String, String> p = new HashMap<String, String>();
|
Map<String, String> p = new HashMap<String, String>();
|
||||||
int next = "Digest ".length();
|
int next = "Digest ".length();
|
||||||
while (next < auth.length()) {
|
while (next < auth.length()) {
|
||||||
|
|||||||
@@ -16,26 +16,23 @@ package com.google.gerrit.httpd;
|
|||||||
|
|
||||||
import com.google.gerrit.reviewdb.client.Account;
|
import com.google.gerrit.reviewdb.client.Account;
|
||||||
import com.google.gerrit.reviewdb.client.AccountExternalId;
|
import com.google.gerrit.reviewdb.client.AccountExternalId;
|
||||||
|
import com.google.gerrit.server.AccessPath;
|
||||||
import com.google.gerrit.server.CurrentUser;
|
import com.google.gerrit.server.CurrentUser;
|
||||||
import com.google.gerrit.server.account.AuthResult;
|
import com.google.gerrit.server.account.AuthResult;
|
||||||
|
|
||||||
public interface WebSession {
|
public interface WebSession {
|
||||||
public boolean isSignedIn();
|
public boolean isSignedIn();
|
||||||
|
|
||||||
public String getAuthorization();
|
public String getAuthorization();
|
||||||
|
|
||||||
public boolean isValidAuthorization(String keyIn);
|
public boolean isValidAuthorization(String keyIn);
|
||||||
|
|
||||||
public AccountExternalId.Key getLastLoginExternalId();
|
public AccountExternalId.Key getLastLoginExternalId();
|
||||||
|
|
||||||
public CurrentUser getCurrentUser();
|
public CurrentUser getCurrentUser();
|
||||||
|
|
||||||
public void login(AuthResult res, boolean rememberMe);
|
public void login(AuthResult res, boolean rememberMe);
|
||||||
|
|
||||||
/** Set the user account for this current request only. */
|
/** Set the user account for this current request only. */
|
||||||
public void setUserAccountId(Account.Id id);
|
public void setUserAccountId(Account.Id id);
|
||||||
|
public boolean isAccessPathOk(AccessPath path);
|
||||||
|
public void setAccessPathOk(AccessPath path, boolean ok);
|
||||||
|
|
||||||
public void logout();
|
public void logout();
|
||||||
|
|
||||||
public String getSessionId();
|
public String getSessionId();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ import java.util.Set;
|
|||||||
public class AnonymousUser extends CurrentUser {
|
public class AnonymousUser extends CurrentUser {
|
||||||
@Inject
|
@Inject
|
||||||
AnonymousUser(CapabilityControl.Factory capabilityControlFactory) {
|
AnonymousUser(CapabilityControl.Factory capabilityControlFactory) {
|
||||||
super(capabilityControlFactory, AccessPath.UNKNOWN);
|
super(capabilityControlFactory);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -33,15 +33,12 @@ import java.util.Set;
|
|||||||
*/
|
*/
|
||||||
public abstract class CurrentUser {
|
public abstract class CurrentUser {
|
||||||
private final CapabilityControl.Factory capabilityControlFactory;
|
private final CapabilityControl.Factory capabilityControlFactory;
|
||||||
private final AccessPath accessPath;
|
private AccessPath accessPath = AccessPath.UNKNOWN;
|
||||||
|
|
||||||
private CapabilityControl capabilities;
|
private CapabilityControl capabilities;
|
||||||
|
|
||||||
protected CurrentUser(
|
protected CurrentUser(CapabilityControl.Factory capabilityControlFactory) {
|
||||||
CapabilityControl.Factory capabilityControlFactory,
|
|
||||||
AccessPath accessPath) {
|
|
||||||
this.capabilityControlFactory = capabilityControlFactory;
|
this.capabilityControlFactory = capabilityControlFactory;
|
||||||
this.accessPath = accessPath;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** How this user is accessing the Gerrit Code Review application. */
|
/** How this user is accessing the Gerrit Code Review application. */
|
||||||
@@ -49,6 +46,10 @@ public abstract class CurrentUser {
|
|||||||
return accessPath;
|
return accessPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setAccessPath(AccessPath path) {
|
||||||
|
accessPath = path;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the set of groups the user is currently a member of.
|
* Get the set of groups the user is currently a member of.
|
||||||
* <p>
|
* <p>
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ import com.google.inject.Inject;
|
|||||||
import com.google.inject.OutOfScopeException;
|
import com.google.inject.OutOfScopeException;
|
||||||
import com.google.inject.Provider;
|
import com.google.inject.Provider;
|
||||||
import com.google.inject.Singleton;
|
import com.google.inject.Singleton;
|
||||||
|
import com.google.inject.util.Providers;
|
||||||
|
|
||||||
import org.eclipse.jgit.lib.PersonIdent;
|
import org.eclipse.jgit.lib.PersonIdent;
|
||||||
import org.eclipse.jgit.util.SystemReader;
|
import org.eclipse.jgit.util.SystemReader;
|
||||||
@@ -90,20 +91,19 @@ public class IdentifiedUser extends CurrentUser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public IdentifiedUser create(final Account.Id id) {
|
public IdentifiedUser create(final Account.Id id) {
|
||||||
return create(AccessPath.UNKNOWN, null, id);
|
return create((SocketAddress) null, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IdentifiedUser create(Provider<ReviewDb> db, Account.Id id) {
|
public IdentifiedUser create(Provider<ReviewDb> db, Account.Id id) {
|
||||||
return new IdentifiedUser(capabilityControlFactory, AccessPath.UNKNOWN,
|
return new IdentifiedUser(capabilityControlFactory,
|
||||||
authConfig, anonymousCowardName, canonicalUrl, realm, accountCache,
|
authConfig, anonymousCowardName, canonicalUrl, realm, accountCache,
|
||||||
groupBackend, null, db, id);
|
groupBackend, null, db, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IdentifiedUser create(AccessPath accessPath,
|
public IdentifiedUser create(SocketAddress remotePeer, Account.Id id) {
|
||||||
Provider<SocketAddress> remotePeerProvider, Account.Id id) {
|
return new IdentifiedUser(capabilityControlFactory,
|
||||||
return new IdentifiedUser(capabilityControlFactory, accessPath,
|
|
||||||
authConfig, anonymousCowardName, canonicalUrl, realm, accountCache,
|
authConfig, anonymousCowardName, canonicalUrl, realm, accountCache,
|
||||||
groupBackend, remotePeerProvider, null, id);
|
groupBackend, Providers.of(remotePeer), null, id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,9 +149,8 @@ public class IdentifiedUser extends CurrentUser {
|
|||||||
this.dbProvider = dbProvider;
|
this.dbProvider = dbProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IdentifiedUser create(final AccessPath accessPath,
|
public IdentifiedUser create(Account.Id id) {
|
||||||
final Account.Id id) {
|
return new IdentifiedUser(capabilityControlFactory,
|
||||||
return new IdentifiedUser(capabilityControlFactory, accessPath,
|
|
||||||
authConfig, anonymousCowardName, canonicalUrl, realm, accountCache,
|
authConfig, anonymousCowardName, canonicalUrl, realm, accountCache,
|
||||||
groupBackend, remotePeerProvider, dbProvider, id);
|
groupBackend, remotePeerProvider, dbProvider, id);
|
||||||
}
|
}
|
||||||
@@ -187,7 +186,6 @@ public class IdentifiedUser extends CurrentUser {
|
|||||||
|
|
||||||
private IdentifiedUser(
|
private IdentifiedUser(
|
||||||
CapabilityControl.Factory capabilityControlFactory,
|
CapabilityControl.Factory capabilityControlFactory,
|
||||||
final AccessPath accessPath,
|
|
||||||
final AuthConfig authConfig,
|
final AuthConfig authConfig,
|
||||||
final String anonymousCowardName,
|
final String anonymousCowardName,
|
||||||
final Provider<String> canonicalUrl,
|
final Provider<String> canonicalUrl,
|
||||||
@@ -195,7 +193,7 @@ public class IdentifiedUser extends CurrentUser {
|
|||||||
final GroupBackend groupBackend,
|
final GroupBackend groupBackend,
|
||||||
@Nullable final Provider<SocketAddress> remotePeerProvider,
|
@Nullable final Provider<SocketAddress> remotePeerProvider,
|
||||||
@Nullable final Provider<ReviewDb> dbProvider, final Account.Id id) {
|
@Nullable final Provider<ReviewDb> dbProvider, final Account.Id id) {
|
||||||
super(capabilityControlFactory, accessPath);
|
super(capabilityControlFactory);
|
||||||
this.canonicalUrl = canonicalUrl;
|
this.canonicalUrl = canonicalUrl;
|
||||||
this.accountCache = accountCache;
|
this.accountCache = accountCache;
|
||||||
this.groupBackend = groupBackend;
|
this.groupBackend = groupBackend;
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ public class InternalUser extends CurrentUser {
|
|||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
protected InternalUser(CapabilityControl.Factory capabilityControlFactory) {
|
protected InternalUser(CapabilityControl.Factory capabilityControlFactory) {
|
||||||
super(capabilityControlFactory, AccessPath.UNKNOWN);
|
super(capabilityControlFactory);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ public class PeerDaemonUser extends CurrentUser {
|
|||||||
@Inject
|
@Inject
|
||||||
protected PeerDaemonUser(CapabilityControl.Factory capabilityControlFactory,
|
protected PeerDaemonUser(CapabilityControl.Factory capabilityControlFactory,
|
||||||
@Assisted SocketAddress peer) {
|
@Assisted SocketAddress peer) {
|
||||||
super(capabilityControlFactory, AccessPath.SSH_COMMAND);
|
super(capabilityControlFactory);
|
||||||
this.peer = peer;
|
this.peer = peer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ package com.google.gerrit.server.query.change;
|
|||||||
import com.google.gerrit.reviewdb.client.AccountGroup;
|
import com.google.gerrit.reviewdb.client.AccountGroup;
|
||||||
import com.google.gerrit.reviewdb.client.AccountProjectWatch;
|
import com.google.gerrit.reviewdb.client.AccountProjectWatch;
|
||||||
import com.google.gerrit.reviewdb.client.Change;
|
import com.google.gerrit.reviewdb.client.Change;
|
||||||
import com.google.gerrit.server.AccessPath;
|
|
||||||
import com.google.gerrit.server.CurrentUser;
|
import com.google.gerrit.server.CurrentUser;
|
||||||
import com.google.gerrit.server.account.CapabilityControl;
|
import com.google.gerrit.server.account.CapabilityControl;
|
||||||
import com.google.gerrit.server.account.GroupMembership;
|
import com.google.gerrit.server.account.GroupMembership;
|
||||||
@@ -37,7 +36,7 @@ public final class SingleGroupUser extends CurrentUser {
|
|||||||
|
|
||||||
public SingleGroupUser(CapabilityControl.Factory capabilityControlFactory,
|
public SingleGroupUser(CapabilityControl.Factory capabilityControlFactory,
|
||||||
Set<AccountGroup.UUID> groups) {
|
Set<AccountGroup.UUID> groups) {
|
||||||
super(capabilityControlFactory, AccessPath.UNKNOWN);
|
super(capabilityControlFactory);
|
||||||
this.groups = new ListGroupMembership(groups);
|
this.groups = new ListGroupMembership(groups);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,7 +33,6 @@ import com.google.gerrit.reviewdb.client.Change;
|
|||||||
import com.google.gerrit.reviewdb.client.Project;
|
import com.google.gerrit.reviewdb.client.Project;
|
||||||
import com.google.gerrit.rules.PrologEnvironment;
|
import com.google.gerrit.rules.PrologEnvironment;
|
||||||
import com.google.gerrit.rules.RulesCache;
|
import com.google.gerrit.rules.RulesCache;
|
||||||
import com.google.gerrit.server.AccessPath;
|
|
||||||
import com.google.gerrit.server.CurrentUser;
|
import com.google.gerrit.server.CurrentUser;
|
||||||
import com.google.gerrit.server.account.CapabilityControl;
|
import com.google.gerrit.server.account.CapabilityControl;
|
||||||
import com.google.gerrit.server.account.GroupMembership;
|
import com.google.gerrit.server.account.GroupMembership;
|
||||||
@@ -415,7 +414,7 @@ public class RefControlTest extends TestCase {
|
|||||||
private final GroupMembership groups;
|
private final GroupMembership groups;
|
||||||
|
|
||||||
MockUser(String name, AccountGroup.UUID[] groupId) {
|
MockUser(String name, AccountGroup.UUID[] groupId) {
|
||||||
super(RefControlTest.this.capabilityControlFactory, AccessPath.UNKNOWN);
|
super(RefControlTest.this.capabilityControlFactory);
|
||||||
username = name;
|
username = name;
|
||||||
ArrayList<AccountGroup.UUID> groupIds = Lists.newArrayList(groupId);
|
ArrayList<AccountGroup.UUID> groupIds = Lists.newArrayList(groupId);
|
||||||
groupIds.add(registered);
|
groupIds.add(registered);
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ import com.google.gerrit.server.git.GitRepositoryManager;
|
|||||||
import com.google.gerrit.server.project.ProjectControl;
|
import com.google.gerrit.server.project.ProjectControl;
|
||||||
import com.google.gerrit.sshd.SshScope.Context;
|
import com.google.gerrit.sshd.SshScope.Context;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import com.google.inject.Provider;
|
|
||||||
|
|
||||||
import org.apache.sshd.server.Environment;
|
import org.apache.sshd.server.Environment;
|
||||||
import org.eclipse.jgit.errors.RepositoryNotFoundException;
|
import org.eclipse.jgit.errors.RepositoryNotFoundException;
|
||||||
@@ -29,7 +28,6 @@ import org.eclipse.jgit.lib.Repository;
|
|||||||
import org.kohsuke.args4j.Argument;
|
import org.kohsuke.args4j.Argument;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.SocketAddress;
|
|
||||||
|
|
||||||
public abstract class AbstractGitCommand extends BaseCommand {
|
public abstract class AbstractGitCommand extends BaseCommand {
|
||||||
@Argument(index = 0, metaVar = "PROJECT.git", required = true, usage = "project name")
|
@Argument(index = 0, metaVar = "PROJECT.git", required = true, usage = "project name")
|
||||||
@@ -84,13 +82,10 @@ public abstract class AbstractGitCommand extends BaseCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private SshSession newSession() {
|
private SshSession newSession() {
|
||||||
return new SshSession(session, session.getRemoteAddress(), userFactory
|
SshSession n = new SshSession(session, session.getRemoteAddress(),
|
||||||
.create(AccessPath.GIT, new Provider<SocketAddress>() {
|
userFactory.create(session.getRemoteAddress(), user.getAccountId()));
|
||||||
@Override
|
n.setAccessPath(AccessPath.GIT);
|
||||||
public SocketAddress get() {
|
return n;
|
||||||
return session.getRemoteAddress();
|
|
||||||
}
|
|
||||||
}, user.getAccountId()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void service() throws IOException, Failure {
|
private void service() throws IOException, Failure {
|
||||||
|
|||||||
@@ -15,7 +15,6 @@
|
|||||||
package com.google.gerrit.sshd;
|
package com.google.gerrit.sshd;
|
||||||
|
|
||||||
import com.google.gerrit.reviewdb.client.AccountSshKey;
|
import com.google.gerrit.reviewdb.client.AccountSshKey;
|
||||||
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;
|
||||||
@@ -23,7 +22,6 @@ 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;
|
||||||
import com.google.inject.Provider;
|
|
||||||
import com.google.inject.Singleton;
|
import com.google.inject.Singleton;
|
||||||
|
|
||||||
import org.apache.commons.codec.binary.Base64;
|
import org.apache.commons.codec.binary.Base64;
|
||||||
@@ -43,7 +41,6 @@ import java.io.File;
|
|||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.FileReader;
|
import java.io.FileReader;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.SocketAddress;
|
|
||||||
import java.security.KeyPair;
|
import java.security.KeyPair;
|
||||||
import java.security.PublicKey;
|
import java.security.PublicKey;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
@@ -201,13 +198,7 @@ class DatabasePubKeyAuth implements PublickeyAuthenticator {
|
|||||||
|
|
||||||
private IdentifiedUser createUser(final SshSession sd,
|
private IdentifiedUser createUser(final SshSession sd,
|
||||||
final SshKeyCacheEntry key) {
|
final SshKeyCacheEntry key) {
|
||||||
return userFactory.create(AccessPath.SSH_COMMAND,
|
return userFactory.create(sd.getRemoteAddress(), key.getAccount());
|
||||||
new Provider<SocketAddress>() {
|
|
||||||
@Override
|
|
||||||
public SocketAddress get() {
|
|
||||||
return sd.getRemoteAddress();
|
|
||||||
}
|
|
||||||
}, key.getAccount());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private SshKeyCacheEntry find(final Iterable<SshKeyCacheEntry> keyList,
|
private SshKeyCacheEntry find(final Iterable<SshKeyCacheEntry> keyList,
|
||||||
|
|||||||
@@ -73,8 +73,7 @@ class SshScope {
|
|||||||
public CurrentUser getCurrentUser() {
|
public CurrentUser getCurrentUser() {
|
||||||
final CurrentUser user = session.getCurrentUser();
|
final CurrentUser user = session.getCurrentUser();
|
||||||
if (user instanceof IdentifiedUser) {
|
if (user instanceof IdentifiedUser) {
|
||||||
return userFactory.create(user.getAccessPath(), //
|
return userFactory.create(((IdentifiedUser) user).getAccountId());
|
||||||
((IdentifiedUser) user).getAccountId());
|
|
||||||
}
|
}
|
||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
package com.google.gerrit.sshd;
|
package com.google.gerrit.sshd;
|
||||||
|
|
||||||
|
import com.google.gerrit.server.AccessPath;
|
||||||
import com.google.gerrit.server.CurrentUser;
|
import com.google.gerrit.server.CurrentUser;
|
||||||
|
|
||||||
import org.apache.sshd.common.Session.AttributeKey;
|
import org.apache.sshd.common.Session.AttributeKey;
|
||||||
@@ -43,6 +44,7 @@ public class SshSession {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SshSession(SshSession parent, SocketAddress peer, CurrentUser user) {
|
SshSession(SshSession parent, SocketAddress peer, CurrentUser user) {
|
||||||
|
user.setAccessPath(AccessPath.SSH_COMMAND);
|
||||||
this.sessionId = parent.sessionId;
|
this.sessionId = parent.sessionId;
|
||||||
this.remoteAddress = peer;
|
this.remoteAddress = peer;
|
||||||
if (parent.remoteAddress == peer) {
|
if (parent.remoteAddress == peer) {
|
||||||
@@ -83,6 +85,10 @@ public class SshSession {
|
|||||||
authError = error;
|
authError = error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setAccessPath(AccessPath path) {
|
||||||
|
identity.setAccessPath(path);
|
||||||
|
}
|
||||||
|
|
||||||
/** @return {@code true} if the authentication did not succeed. */
|
/** @return {@code true} if the authentication did not succeed. */
|
||||||
boolean isAuthenticationError() {
|
boolean isAuthenticationError() {
|
||||||
return authError != null;
|
return authError != null;
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ package com.google.gerrit.sshd;
|
|||||||
|
|
||||||
import com.google.common.util.concurrent.Atomics;
|
import com.google.common.util.concurrent.Atomics;
|
||||||
import com.google.gerrit.reviewdb.client.Account;
|
import com.google.gerrit.reviewdb.client.Account;
|
||||||
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;
|
||||||
@@ -116,14 +115,8 @@ public final class SuExec extends BaseCommand {
|
|||||||
} else {
|
} else {
|
||||||
peer = peerAddress;
|
peer = peerAddress;
|
||||||
}
|
}
|
||||||
|
return new SshSession(session.get(), peer,
|
||||||
return new SshSession(session.get(), peer, userFactory.create(
|
userFactory.create(peer, accountId));
|
||||||
AccessPath.SSH_COMMAND, new Provider<SocketAddress>() {
|
|
||||||
@Override
|
|
||||||
public SocketAddress get() {
|
|
||||||
return peer;
|
|
||||||
}
|
|
||||||
}, accountId));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String join(List<String> args) {
|
private static String join(List<String> args) {
|
||||||
|
|||||||
Reference in New Issue
Block a user