diff --git a/build.sbt b/build.sbt index f116a7e..ee12844 100644 --- a/build.sbt +++ b/build.sbt @@ -42,7 +42,7 @@ "org.apache.commons" % "commons-email" % "1.5", "commons-net" % "commons-net" % "3.8.0", "org.apache.httpcomponents" % "httpclient" % "4.5.13", - "org.apache.sshd" % "apache-sshd" % "2.1.0" exclude ("org.slf4j", "slf4j-jdk14") exclude ("org.apache.sshd", "sshd-mina") exclude ("org.apache.sshd", "sshd-netty"), + "org.apache.sshd" % "apache-sshd" % "2.7.0" exclude ("org.slf4j", "slf4j-jdk14") exclude ("org.apache.sshd", "sshd-mina") exclude ("org.apache.sshd", "sshd-netty"), "org.apache.tika" % "tika-core" % "2.1.0", "com.github.takezoe" %% "blocking-slick-32" % "0.0.12" cross CrossVersion.for3Use2_13, "com.novell.ldap" % "jldap" % "2009-10-07", diff --git a/src/main/scala/gitbucket/core/ssh/GitCommand.scala b/src/main/scala/gitbucket/core/ssh/GitCommand.scala index 233942e..7e8fff5 100644 --- a/src/main/scala/gitbucket/core/ssh/GitCommand.scala +++ b/src/main/scala/gitbucket/core/ssh/GitCommand.scala @@ -5,18 +5,20 @@ import gitbucket.core.service.{AccountService, DeployKeyService, RepositoryService, SystemSettingsService} import gitbucket.core.servlet.{CommitLogHook, Database} import gitbucket.core.util.Directory -import org.apache.sshd.server.{Environment, ExitCallback, SessionAware} +import org.apache.sshd.server.{Environment, ExitCallback} import org.apache.sshd.server.command.{Command, CommandFactory} -import org.apache.sshd.server.session.ServerSession +import org.apache.sshd.server.session.{ServerSession, ServerSessionAware} import org.slf4j.LoggerFactory -import java.io.{File, InputStream, OutputStream} +import java.io.{File, InputStream, OutputStream} import org.eclipse.jgit.api.Git import Directory._ import gitbucket.core.ssh.PublicKeyAuthenticator.AuthType +import org.apache.sshd.server.channel.ChannelSession import org.eclipse.jgit.transport.{ReceivePack, UploadPack} import org.apache.sshd.server.shell.UnknownCommand import org.eclipse.jgit.errors.RepositoryNotFoundException + import scala.util.Using object GitCommand { @@ -24,7 +26,7 @@ val SimpleCommandRegex = """\Agit-(upload|receive)-pack '/(.+\.git)'\Z""".r } -abstract class GitCommand extends Command with SessionAware { +abstract class GitCommand extends Command with ServerSessionAware { private val logger = LoggerFactory.getLogger(classOf[GitCommand]) @@ -57,12 +59,12 @@ } } - final override def start(env: Environment): Unit = { + final override def start(channel: ChannelSession, env: Environment): Unit = { val thread = new Thread(newTask()) thread.start() } - override def destroy(): Unit = {} + override def destroy(channel: ChannelSession): Unit = {} override def setExitCallback(callback: ExitCallback): Unit = { this.callback = callback @@ -230,7 +232,7 @@ class GitCommandFactory(baseUrl: String, sshUrl: Option[String]) extends CommandFactory { private val logger = LoggerFactory.getLogger(classOf[GitCommandFactory]) - override def createCommand(command: String): Command = { + override def createCommand(channel: ChannelSession, command: String): Command = { import GitCommand._ logger.debug(s"command: $command") diff --git a/src/main/scala/gitbucket/core/ssh/NoShell.scala b/src/main/scala/gitbucket/core/ssh/NoShell.scala index b350e26..a92f246 100644 --- a/src/main/scala/gitbucket/core/ssh/NoShell.scala +++ b/src/main/scala/gitbucket/core/ssh/NoShell.scala @@ -1,20 +1,22 @@ package gitbucket.core.ssh import gitbucket.core.service.SystemSettingsService.SshAddress -import org.apache.sshd.common.Factory +import org.apache.sshd.server.channel.ChannelSession import org.apache.sshd.server.{Environment, ExitCallback} import org.apache.sshd.server.command.Command -import java.io.{OutputStream, InputStream} +import org.apache.sshd.server.shell.ShellFactory + +import java.io.{InputStream, OutputStream} import org.eclipse.jgit.lib.Constants -class NoShell(sshAddress: SshAddress) extends Factory[Command] { - override def create(): Command = new Command() { +class NoShell(sshAddress: SshAddress) extends ShellFactory { + override def createShell(channel: ChannelSession): Command = new Command() { private var in: InputStream = null private var out: OutputStream = null private var err: OutputStream = null private var callback: ExitCallback = null - override def start(env: Environment): Unit = { + override def start(channel: ChannelSession, env: Environment): Unit = { val message = """ | Welcome to @@ -40,7 +42,7 @@ callback.onExit(127) } - override def destroy(): Unit = {} + override def destroy(channel: ChannelSession): Unit = {} override def setInputStream(in: InputStream): Unit = { this.in = in diff --git a/src/main/scala/gitbucket/core/ssh/PublicKeyAuthenticator.scala b/src/main/scala/gitbucket/core/ssh/PublicKeyAuthenticator.scala index 2f79f4e..4501e71 100644 --- a/src/main/scala/gitbucket/core/ssh/PublicKeyAuthenticator.scala +++ b/src/main/scala/gitbucket/core/ssh/PublicKeyAuthenticator.scala @@ -8,13 +8,13 @@ import gitbucket.core.ssh.PublicKeyAuthenticator.AuthType import org.apache.sshd.server.auth.pubkey.PublickeyAuthenticator import org.apache.sshd.server.session.ServerSession -import org.apache.sshd.common.AttributeStore +import org.apache.sshd.common.AttributeRepository import org.slf4j.LoggerFactory object PublicKeyAuthenticator { // put in the ServerSession here to be read by GitCommand later - private val authTypeSessionKey = new AttributeStore.AttributeKey[AuthType] + private val authTypeSessionKey = new AttributeRepository.AttributeKey[AuthType] def putAuthType(serverSession: ServerSession, authType: AuthType): Unit = serverSession.setAttribute(authTypeSessionKey, authType) diff --git a/src/test/scala/gitbucket/core/ssh/GitCommandSpec.scala b/src/test/scala/gitbucket/core/ssh/GitCommandSpec.scala index 35d88fa..f899731 100644 --- a/src/test/scala/gitbucket/core/ssh/GitCommandSpec.scala +++ b/src/test/scala/gitbucket/core/ssh/GitCommandSpec.scala @@ -1,5 +1,6 @@ package gitbucket.core.ssh +import org.apache.sshd.server.channel.ChannelSession import org.apache.sshd.server.shell.UnknownCommand import org.scalatest.funspec.AnyFunSpec @@ -8,30 +9,41 @@ val factory = new GitCommandFactory("http://localhost:8080", None) describe("createCommand") { + val channel = new ChannelSession() it("should return GitReceivePack when command is git-receive-pack") { - assert(factory.createCommand("git-receive-pack '/owner/repo.git'").isInstanceOf[DefaultGitReceivePack] == true) assert( - factory.createCommand("git-receive-pack '/owner/repo.wiki.git'").isInstanceOf[DefaultGitReceivePack] == true + factory.createCommand(channel, "git-receive-pack '/owner/repo.git'").isInstanceOf[DefaultGitReceivePack] == true + ) + assert( + factory + .createCommand(channel, "git-receive-pack '/owner/repo.wiki.git'") + .isInstanceOf[DefaultGitReceivePack] == true ) } it("should return GitUploadPack when command is git-upload-pack") { - assert(factory.createCommand("git-upload-pack '/owner/repo.git'").isInstanceOf[DefaultGitUploadPack] == true) - assert(factory.createCommand("git-upload-pack '/owner/repo.wiki.git'").isInstanceOf[DefaultGitUploadPack] == true) + assert( + factory.createCommand(channel, "git-upload-pack '/owner/repo.git'").isInstanceOf[DefaultGitUploadPack] == true + ) + assert( + factory + .createCommand(channel, "git-upload-pack '/owner/repo.wiki.git'") + .isInstanceOf[DefaultGitUploadPack] == true + ) } it("should return UnknownCommand when command is not git-(upload|receive)-pack") { - assert(factory.createCommand("git- '/owner/repo.git'").isInstanceOf[UnknownCommand] == true) - assert(factory.createCommand("git-pack '/owner/repo.git'").isInstanceOf[UnknownCommand] == true) - assert(factory.createCommand("git-a-pack '/owner/repo.git'").isInstanceOf[UnknownCommand] == true) - assert(factory.createCommand("git-up-pack '/owner/repo.git'").isInstanceOf[UnknownCommand] == true) - assert(factory.createCommand("\ngit-upload-pack '/owner/repo.git'").isInstanceOf[UnknownCommand] == true) + assert(factory.createCommand(channel, "git- '/owner/repo.git'").isInstanceOf[UnknownCommand] == true) + assert(factory.createCommand(channel, "git-pack '/owner/repo.git'").isInstanceOf[UnknownCommand] == true) + assert(factory.createCommand(channel, "git-a-pack '/owner/repo.git'").isInstanceOf[UnknownCommand] == true) + assert(factory.createCommand(channel, "git-up-pack '/owner/repo.git'").isInstanceOf[UnknownCommand] == true) + assert(factory.createCommand(channel, "\ngit-upload-pack '/owner/repo.git'").isInstanceOf[UnknownCommand] == true) } it("should return UnknownCommand when git command has no valid arguments") { // must be: git-upload-pack '/owner/repository_name.git' - assert(factory.createCommand("git-upload-pack").isInstanceOf[UnknownCommand] == true) - assert(factory.createCommand("git-upload-pack /owner/repo.git").isInstanceOf[UnknownCommand] == true) - assert(factory.createCommand("git-upload-pack 'owner/repo.git'").isInstanceOf[UnknownCommand] == true) - assert(factory.createCommand("git-upload-pack '/ownerrepo.git'").isInstanceOf[UnknownCommand] == true) - assert(factory.createCommand("git-upload-pack '/owner/repo.wiki'").isInstanceOf[UnknownCommand] == true) + assert(factory.createCommand(channel, "git-upload-pack").isInstanceOf[UnknownCommand] == true) + assert(factory.createCommand(channel, "git-upload-pack /owner/repo.git").isInstanceOf[UnknownCommand] == true) + assert(factory.createCommand(channel, "git-upload-pack 'owner/repo.git'").isInstanceOf[UnknownCommand] == true) + assert(factory.createCommand(channel, "git-upload-pack '/ownerrepo.git'").isInstanceOf[UnknownCommand] == true) + assert(factory.createCommand(channel, "git-upload-pack '/owner/repo.wiki'").isInstanceOf[UnknownCommand] == true) } }