From ff7eef03990faa02d7ad1ff845f6e9525275fd95 Mon Sep 17 00:00:00 2001 From: Brad Larson Date: Tue, 15 May 2012 16:58:01 -0500 Subject: [PATCH] Apply @RequiresCapability to REST API Move the @RequiresCapability from SSHD to gerrit-extension-api. Modify the RestApiServlet to check the current user has the required capabilities. All RestApiServlets must now inject the currentUser provider in their constructor and pass it to the super class. Signed-off-by: Brad Larson Change-Id: Iffc9bc99b8d2fafd07bf624008719b0ec647ce7d --- .../annotations}/RequiresCapability.java | 5 ++- .../google/gerrit/httpd/RestApiServlet.java | 39 ++++++++++++++++++- .../account/AccountCapabilitiesServlet.java | 3 +- .../httpd/rpc/change/ListChangesServlet.java | 5 ++- .../rpc/project/ListProjectsServlet.java | 5 ++- .../com/google/gerrit/sshd/AliasCommand.java | 1 + .../google/gerrit/sshd/DispatchCommand.java | 1 + .../gerrit/sshd/commands/AdminQueryShell.java | 2 +- .../gerrit/sshd/commands/AdminSetParent.java | 2 +- .../sshd/commands/CreateAccountCommand.java | 2 +- .../sshd/commands/CreateGroupCommand.java | 2 +- .../sshd/commands/CreateProjectCommand.java | 2 +- .../gerrit/sshd/commands/FlushCaches.java | 2 +- .../gerrit/sshd/commands/KillCommand.java | 2 +- .../sshd/commands/PluginInstallCommand.java | 2 +- .../gerrit/sshd/commands/PluginLsCommand.java | 2 +- .../sshd/commands/PluginReloadCommand.java | 2 +- .../sshd/commands/PluginRemoveCommand.java | 2 +- .../gerrit/sshd/commands/ShowCaches.java | 2 +- .../gerrit/sshd/commands/ShowConnections.java | 2 +- 20 files changed, 66 insertions(+), 19 deletions(-) rename {gerrit-sshd/src/main/java/com/google/gerrit/sshd => gerrit-extension-api/src/main/java/com/google/gerrit/extensions/annotations}/RequiresCapability.java (85%) diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/RequiresCapability.java b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/annotations/RequiresCapability.java similarity index 85% rename from gerrit-sshd/src/main/java/com/google/gerrit/sshd/RequiresCapability.java rename to gerrit-extension-api/src/main/java/com/google/gerrit/extensions/annotations/RequiresCapability.java index cc41a79a57..382f4eafb9 100644 --- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/RequiresCapability.java +++ b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/annotations/RequiresCapability.java @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package com.google.gerrit.sshd; +package com.google.gerrit.extensions.annotations; import static java.lang.annotation.RetentionPolicy.RUNTIME; @@ -21,7 +21,8 @@ import java.lang.annotation.Retention; import java.lang.annotation.Target; /** - * Annotation on {@link SshCommand} declaring a capability must be granted. + * Annotation on {@link SshCommand} or {@link RestApiServlet} declaring a + * capability must be granted. */ @Target({ElementType.TYPE}) @Retention(RUNTIME) diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/RestApiServlet.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/RestApiServlet.java index 8105e25580..ff41ad8160 100644 --- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/RestApiServlet.java +++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/RestApiServlet.java @@ -15,10 +15,14 @@ package com.google.gerrit.httpd; import com.google.common.base.Strings; +import com.google.gerrit.extensions.annotations.RequiresCapability; +import com.google.gerrit.server.CurrentUser; +import com.google.gerrit.server.account.CapabilityControl; import com.google.gerrit.util.cli.CmdLineParser; -import com.google.gwtjsonrpc.server.RPCServletUtils; import com.google.gwtjsonrpc.common.JsonConstants; +import com.google.gwtjsonrpc.server.RPCServletUtils; import com.google.inject.Inject; +import com.google.inject.Provider; import org.kohsuke.args4j.CmdLineException; import org.slf4j.Logger; @@ -62,12 +66,24 @@ public abstract class RestApiServlet extends HttpServlet { } } + private final Provider currentUser; + + @Inject + protected RestApiServlet(final Provider currentUser) { + this.currentUser = currentUser; + } + @Override protected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { noCache(res); try { + checkRequiresCapability(); super.service(req, res); + } catch (RequireCapabilityException err) { + res.setStatus(HttpServletResponse.SC_FORBIDDEN); + noCache(res); + sendText(req, res, err.getMessage()); } catch (Error err) { handleError(err, req, res); } catch (RuntimeException err) { @@ -75,6 +91,20 @@ public abstract class RestApiServlet extends HttpServlet { } } + private void checkRequiresCapability() throws RequireCapabilityException { + RequiresCapability rc = getClass().getAnnotation(RequiresCapability.class); + if (rc != null) { + CurrentUser user = currentUser.get(); + CapabilityControl ctl = user.getCapabilities(); + if (!ctl.canPerform(rc.value()) && !ctl.canAdministrateServer()) { + String msg = String.format( + "fatal: %s does not have \"%s\" capability.", + user.getUserName(), rc.value()); + throw new RequireCapabilityException(msg); + } + } + } + private static void noCache(HttpServletResponse res) { res.setHeader("Expires", "Fri, 01 Jan 1980 00:00:00 GMT"); res.setHeader("Pragma", "no-cache"); @@ -175,4 +205,11 @@ public abstract class RestApiServlet extends HttpServlet { return true; } } + + @SuppressWarnings("serial") // Never serialized or thrown out of this class. + private static class RequireCapabilityException extends Exception { + public RequireCapabilityException(String msg) { + super(msg); + } + } } diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/account/AccountCapabilitiesServlet.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/account/AccountCapabilitiesServlet.java index 0d0ffe7a95..a33c2093af 100644 --- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/account/AccountCapabilitiesServlet.java +++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/account/AccountCapabilitiesServlet.java @@ -58,8 +58,9 @@ public class AccountCapabilitiesServlet extends RestApiServlet { private final Provider factory; @Inject - AccountCapabilitiesServlet( + AccountCapabilitiesServlet(final Provider currentUser, ParameterParser paramParser, Provider factory) { + super(currentUser); this.paramParser = paramParser; this.factory = factory; } diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/change/ListChangesServlet.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/change/ListChangesServlet.java index 91fc5b0880..b501d43895 100644 --- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/change/ListChangesServlet.java +++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/change/ListChangesServlet.java @@ -15,6 +15,7 @@ package com.google.gerrit.httpd.rpc.change; import com.google.gerrit.httpd.RestApiServlet; +import com.google.gerrit.server.CurrentUser; import com.google.gerrit.server.OutputFormat; import com.google.gerrit.server.query.QueryParseException; import com.google.gerrit.server.query.change.ListChanges; @@ -43,7 +44,9 @@ public class ListChangesServlet extends RestApiServlet { private final Provider factory; @Inject - ListChangesServlet(ParameterParser paramParser, Provider ls) { + ListChangesServlet(final Provider currentUser, + ParameterParser paramParser, Provider ls) { + super(currentUser); this.paramParser = paramParser; this.factory = ls; } diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/ListProjectsServlet.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/ListProjectsServlet.java index 27576408d3..d327d35975 100644 --- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/ListProjectsServlet.java +++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/ListProjectsServlet.java @@ -16,6 +16,7 @@ package com.google.gerrit.httpd.rpc.project; import com.google.common.base.Strings; import com.google.gerrit.httpd.RestApiServlet; +import com.google.gerrit.server.CurrentUser; import com.google.gerrit.server.OutputFormat; import com.google.gerrit.server.project.ListProjects; import com.google.inject.Inject; @@ -36,7 +37,9 @@ public class ListProjectsServlet extends RestApiServlet { private final Provider factory; @Inject - ListProjectsServlet(ParameterParser paramParser, Provider ls) { + ListProjectsServlet(final Provider currentUser, + ParameterParser paramParser, Provider ls) { + super(currentUser); this.paramParser = paramParser; this.factory = ls; } diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/AliasCommand.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/AliasCommand.java index d28d1029b1..9582c936a9 100644 --- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/AliasCommand.java +++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/AliasCommand.java @@ -16,6 +16,7 @@ package com.google.gerrit.sshd; import com.google.common.collect.Lists; import com.google.common.util.concurrent.Atomics; +import com.google.gerrit.extensions.annotations.RequiresCapability; import com.google.gerrit.server.CurrentUser; import com.google.gerrit.server.account.CapabilityControl; import com.google.inject.Provider; diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/DispatchCommand.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/DispatchCommand.java index f0810baaa0..37f141124f 100644 --- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/DispatchCommand.java +++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/DispatchCommand.java @@ -16,6 +16,7 @@ package com.google.gerrit.sshd; import com.google.common.collect.Sets; import com.google.common.util.concurrent.Atomics; +import com.google.gerrit.extensions.annotations.RequiresCapability; import com.google.gerrit.server.CurrentUser; import com.google.gerrit.server.account.CapabilityControl; import com.google.gerrit.sshd.args4j.SubcommandHandler; diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/AdminQueryShell.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/AdminQueryShell.java index 5f1992ccc2..08c650cde9 100644 --- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/AdminQueryShell.java +++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/AdminQueryShell.java @@ -15,8 +15,8 @@ package com.google.gerrit.sshd.commands; import com.google.gerrit.common.data.GlobalCapability; +import com.google.gerrit.extensions.annotations.RequiresCapability; import com.google.gerrit.sshd.AdminHighPriorityCommand; -import com.google.gerrit.sshd.RequiresCapability; import com.google.gerrit.sshd.SshCommand; import com.google.inject.Inject; diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/AdminSetParent.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/AdminSetParent.java index 047cdd4bec..cfd917c611 100644 --- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/AdminSetParent.java +++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/AdminSetParent.java @@ -15,6 +15,7 @@ package com.google.gerrit.sshd.commands; import com.google.gerrit.common.data.GlobalCapability; +import com.google.gerrit.extensions.annotations.RequiresCapability; import com.google.gerrit.reviewdb.client.Project; import com.google.gerrit.server.config.AllProjectsName; import com.google.gerrit.server.git.MetaDataUpdate; @@ -22,7 +23,6 @@ import com.google.gerrit.server.git.ProjectConfig; import com.google.gerrit.server.project.ProjectCache; import com.google.gerrit.server.project.ProjectControl; import com.google.gerrit.server.project.ProjectState; -import com.google.gerrit.sshd.RequiresCapability; import com.google.gerrit.sshd.SshCommand; import com.google.inject.Inject; diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/CreateAccountCommand.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/CreateAccountCommand.java index 29f22949d9..ac7ee082a2 100644 --- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/CreateAccountCommand.java +++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/CreateAccountCommand.java @@ -16,6 +16,7 @@ package com.google.gerrit.sshd.commands; import com.google.gerrit.common.data.GlobalCapability; import com.google.gerrit.common.errors.InvalidSshKeyException; +import com.google.gerrit.extensions.annotations.RequiresCapability; import com.google.gerrit.reviewdb.client.Account; import com.google.gerrit.reviewdb.client.AccountExternalId; import com.google.gerrit.reviewdb.client.AccountGroup; @@ -27,7 +28,6 @@ import com.google.gerrit.server.IdentifiedUser; import com.google.gerrit.server.account.AccountByEmailCache; import com.google.gerrit.server.account.AccountCache; import com.google.gerrit.server.ssh.SshKeyCache; -import com.google.gerrit.sshd.RequiresCapability; import com.google.gerrit.sshd.SshCommand; import com.google.gwtorm.server.OrmDuplicateKeyException; import com.google.gwtorm.server.OrmException; diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/CreateGroupCommand.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/CreateGroupCommand.java index 28b6f4880b..728c20cf0f 100644 --- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/CreateGroupCommand.java +++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/CreateGroupCommand.java @@ -17,10 +17,10 @@ package com.google.gerrit.sshd.commands; import com.google.gerrit.common.data.GlobalCapability; import com.google.gerrit.common.errors.NameAlreadyUsedException; import com.google.gerrit.common.errors.PermissionDeniedException; +import com.google.gerrit.extensions.annotations.RequiresCapability; import com.google.gerrit.reviewdb.client.Account; import com.google.gerrit.reviewdb.client.AccountGroup; import com.google.gerrit.server.account.PerformCreateGroup; -import com.google.gerrit.sshd.RequiresCapability; import com.google.gerrit.sshd.SshCommand; import com.google.gwtorm.server.OrmException; import com.google.inject.Inject; diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/CreateProjectCommand.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/CreateProjectCommand.java index 1f5bc6f442..eafe54f358 100644 --- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/CreateProjectCommand.java +++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/CreateProjectCommand.java @@ -16,6 +16,7 @@ package com.google.gerrit.sshd.commands; import com.google.gerrit.common.data.GlobalCapability; import com.google.gerrit.common.errors.ProjectCreationFailedException; +import com.google.gerrit.extensions.annotations.RequiresCapability; import com.google.gerrit.reviewdb.client.AccountGroup; import com.google.gerrit.reviewdb.client.Project; import com.google.gerrit.reviewdb.client.Project.SubmitType; @@ -23,7 +24,6 @@ import com.google.gerrit.server.project.CreateProject; import com.google.gerrit.server.project.CreateProjectArgs; import com.google.gerrit.server.project.ProjectControl; import com.google.gerrit.server.project.SuggestParentCandidates; -import com.google.gerrit.sshd.RequiresCapability; import com.google.gerrit.sshd.SshCommand; import com.google.inject.Inject; diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/FlushCaches.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/FlushCaches.java index 9ba20ed2a0..1d4cf005c2 100644 --- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/FlushCaches.java +++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/FlushCaches.java @@ -15,9 +15,9 @@ package com.google.gerrit.sshd.commands; import com.google.gerrit.common.data.GlobalCapability; +import com.google.gerrit.extensions.annotations.RequiresCapability; import com.google.gerrit.server.IdentifiedUser; import com.google.gerrit.sshd.BaseCommand; -import com.google.gerrit.sshd.RequiresCapability; import com.google.inject.Inject; import net.sf.ehcache.Ehcache; diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/KillCommand.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/KillCommand.java index 12ab225ad2..83e88e55b0 100644 --- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/KillCommand.java +++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/KillCommand.java @@ -15,11 +15,11 @@ package com.google.gerrit.sshd.commands; import com.google.gerrit.common.data.GlobalCapability; +import com.google.gerrit.extensions.annotations.RequiresCapability; import com.google.gerrit.server.git.WorkQueue; import com.google.gerrit.server.git.WorkQueue.Task; import com.google.gerrit.server.util.IdGenerator; import com.google.gerrit.sshd.AdminHighPriorityCommand; -import com.google.gerrit.sshd.RequiresCapability; import com.google.gerrit.sshd.SshCommand; import com.google.inject.Inject; diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/PluginInstallCommand.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/PluginInstallCommand.java index 2328847661..12722ec133 100644 --- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/PluginInstallCommand.java +++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/PluginInstallCommand.java @@ -16,9 +16,9 @@ package com.google.gerrit.sshd.commands; import com.google.common.base.Strings; import com.google.gerrit.common.data.GlobalCapability; +import com.google.gerrit.extensions.annotations.RequiresCapability; import com.google.gerrit.server.plugins.PluginInstallException; import com.google.gerrit.server.plugins.PluginLoader; -import com.google.gerrit.sshd.RequiresCapability; import com.google.gerrit.sshd.SshCommand; import com.google.inject.Inject; diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/PluginLsCommand.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/PluginLsCommand.java index ff34269d63..6d7490fb03 100644 --- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/PluginLsCommand.java +++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/PluginLsCommand.java @@ -15,9 +15,9 @@ package com.google.gerrit.sshd.commands; import com.google.gerrit.common.data.GlobalCapability; +import com.google.gerrit.extensions.annotations.RequiresCapability; import com.google.gerrit.server.plugins.ListPlugins; import com.google.gerrit.sshd.BaseCommand; -import com.google.gerrit.sshd.RequiresCapability; import com.google.inject.Inject; import org.apache.sshd.server.Environment; diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/PluginReloadCommand.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/PluginReloadCommand.java index d60465cca2..d2429a9320 100644 --- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/PluginReloadCommand.java +++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/PluginReloadCommand.java @@ -17,8 +17,8 @@ package com.google.gerrit.sshd.commands; import com.google.gerrit.common.data.GlobalCapability; import com.google.gerrit.server.plugins.InvalidPluginException; import com.google.gerrit.server.plugins.PluginInstallException; +import com.google.gerrit.extensions.annotations.RequiresCapability; import com.google.gerrit.server.plugins.PluginLoader; -import com.google.gerrit.sshd.RequiresCapability; import com.google.gerrit.sshd.SshCommand; import com.google.inject.Inject; diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/PluginRemoveCommand.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/PluginRemoveCommand.java index 6444e71ee7..8baab77661 100644 --- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/PluginRemoveCommand.java +++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/PluginRemoveCommand.java @@ -16,8 +16,8 @@ package com.google.gerrit.sshd.commands; import com.google.common.collect.Sets; import com.google.gerrit.common.data.GlobalCapability; +import com.google.gerrit.extensions.annotations.RequiresCapability; import com.google.gerrit.server.plugins.PluginLoader; -import com.google.gerrit.sshd.RequiresCapability; import com.google.gerrit.sshd.SshCommand; import com.google.inject.Inject; diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ShowCaches.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ShowCaches.java index 97a0d8606d..66013e6c06 100644 --- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ShowCaches.java +++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ShowCaches.java @@ -16,11 +16,11 @@ package com.google.gerrit.sshd.commands; import com.google.gerrit.common.Version; import com.google.gerrit.common.data.GlobalCapability; +import com.google.gerrit.extensions.annotations.RequiresCapability; import com.google.gerrit.extensions.events.LifecycleListener; import com.google.gerrit.server.config.SitePath; import com.google.gerrit.server.git.WorkQueue; import com.google.gerrit.server.git.WorkQueue.Task; -import com.google.gerrit.sshd.RequiresCapability; import com.google.gerrit.sshd.SshDaemon; import com.google.inject.Inject; diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ShowConnections.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ShowConnections.java index 4085dcb09c..a1a5b8f369 100644 --- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ShowConnections.java +++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ShowConnections.java @@ -15,10 +15,10 @@ package com.google.gerrit.sshd.commands; import com.google.gerrit.common.data.GlobalCapability; +import com.google.gerrit.extensions.annotations.RequiresCapability; import com.google.gerrit.server.CurrentUser; import com.google.gerrit.server.IdentifiedUser; import com.google.gerrit.server.util.IdGenerator; -import com.google.gerrit.sshd.RequiresCapability; import com.google.gerrit.sshd.SshCommand; import com.google.gerrit.sshd.SshDaemon; import com.google.gerrit.sshd.SshSession;