From d41034ad2ff334707a58ace5f3cd1de5fcfa1815 Mon Sep 17 00:00:00 2001
From: James Moger <james.moger@gitblit.com>
Date: Fri, 18 Sep 2015 08:30:29 -0400
Subject: [PATCH] Update to SSHD 1.0.0

---
 src/main/java/com/gitblit/transport/ssh/SshKey.java                        |    7 
 src/test/java/com/gitblit/tests/SshUnitTest.java                           |   12 +-
 .classpath                                                                 |    2 
 src/test/java/com/gitblit/tests/SshDaemonTest.java                         |    4 
 src/main/java/com/gitblit/transport/ssh/FileKeyPairProvider.java           |  154 ++++++++++++++++++++++++++++++
 src/main/java/com/gitblit/transport/ssh/SshServerSession.java              |    4 
 src/main/java/com/gitblit/transport/ssh/SshServerSessionFactory.java       |    2 
 src/main/java/com/gitblit/transport/ssh/SshDaemon.java                     |   23 ++--
 src/main/java/com/gitblit/transport/ssh/DisabledFilesystemFactory.java     |   35 ++----
 src/main/java/com/gitblit/transport/ssh/UsernamePasswordAuthenticator.java |    2 
 src/main/java/com/gitblit/transport/ssh/SshKeyAuthenticator.java           |    2 
 build.moxie                                                                |    2 
 src/main/java/com/gitblit/transport/ssh/SshDaemonClient.java               |    2 
 gitblit.iml                                                                |    6 
 src/main/java/com/gitblit/transport/ssh/NonForwardingFilter.java           |    7 
 15 files changed, 205 insertions(+), 59 deletions(-)

diff --git a/.classpath b/.classpath
index 1c01cdf..a04c9e2 100644
--- a/.classpath
+++ b/.classpath
@@ -52,7 +52,7 @@
 	<classpathentry kind="lib" path="ext/bcprov-jdk15on-1.52.jar" sourcepath="ext/src/bcprov-jdk15on-1.52.jar" />
 	<classpathentry kind="lib" path="ext/bcmail-jdk15on-1.52.jar" sourcepath="ext/src/bcmail-jdk15on-1.52.jar" />
 	<classpathentry kind="lib" path="ext/bcpkix-jdk15on-1.52.jar" sourcepath="ext/src/bcpkix-jdk15on-1.52.jar" />
-	<classpathentry kind="lib" path="ext/sshd-core-0.14.0.jar" sourcepath="ext/src/sshd-core-0.14.0.jar" />
+	<classpathentry kind="lib" path="ext/sshd-core-1.0.0.jar" sourcepath="ext/src/sshd-core-1.0.0.jar" />
 	<classpathentry kind="lib" path="ext/mina-core-2.0.9.jar" sourcepath="ext/src/mina-core-2.0.9.jar" />
 	<classpathentry kind="lib" path="ext/rome-0.9.jar" sourcepath="ext/src/rome-0.9.jar" />
 	<classpathentry kind="lib" path="ext/jdom-1.0.jar" sourcepath="ext/src/jdom-1.0.jar" />
diff --git a/build.moxie b/build.moxie
index 845a7a3..3958df8 100644
--- a/build.moxie
+++ b/build.moxie
@@ -111,7 +111,7 @@
   bouncycastle.version : 1.52
   selenium.version : 2.28.0
   wikitext.version : 1.4
-  sshd.version: 0.14.0
+  sshd.version: 1.0.0
   mina.version: 2.0.9
   guice.version : 4.0-beta5
   # Gitblit maintains a fork of guice-servlet
diff --git a/gitblit.iml b/gitblit.iml
index 9f896d1..d6982f3 100644
--- a/gitblit.iml
+++ b/gitblit.iml
@@ -527,13 +527,13 @@
       </library>
     </orderEntry>
     <orderEntry type="module-library">
-      <library name="sshd-core-0.14.0.jar">
+      <library name="sshd-core-1.0.0.jar">
         <CLASSES>
-          <root url="jar://$MODULE_DIR$/ext/sshd-core-0.14.0.jar!/" />
+          <root url="jar://$MODULE_DIR$/ext/sshd-core-1.0.0.jar!/" />
         </CLASSES>
         <JAVADOC />
         <SOURCES>
-          <root url="jar://$MODULE_DIR$/ext/src/sshd-core-0.14.0.jar!/" />
+          <root url="jar://$MODULE_DIR$/ext/src/sshd-core-1.0.0.jar!/" />
         </SOURCES>
       </library>
     </orderEntry>
diff --git a/src/main/java/com/gitblit/transport/ssh/DisabledFilesystemFactory.java b/src/main/java/com/gitblit/transport/ssh/DisabledFilesystemFactory.java
index de661a4..9bab3b8 100644
--- a/src/main/java/com/gitblit/transport/ssh/DisabledFilesystemFactory.java
+++ b/src/main/java/com/gitblit/transport/ssh/DisabledFilesystemFactory.java
@@ -16,31 +16,22 @@
 package com.gitblit.transport.ssh;
 
 import java.io.IOException;
+import java.nio.file.FileSystem;
 
-import org.apache.sshd.common.Session;
 import org.apache.sshd.common.file.FileSystemFactory;
-import org.apache.sshd.common.file.FileSystemView;
-import org.apache.sshd.common.file.SshFile;
+import org.apache.sshd.common.session.Session;
 
 public class DisabledFilesystemFactory implements FileSystemFactory {
 
-	@Override
-	public FileSystemView createFileSystemView(Session session) throws IOException {
-		return new FileSystemView() {
-			@Override
-			public SshFile getFile(SshFile baseDir, String file) {
-				return null;
-			}
-
-			@Override
-			public SshFile getFile(String file) {
-				return null;
-			}
-
-			@Override
-			public FileSystemView getNormalizedView() {
-				return null;
-			}
-		};
-	}
+	 /**
+     * Create user specific file system.
+     *
+     * @param session The session created for the user
+     * @return The current {@link FileSystem} for the provided session
+     * @throws java.io.IOException when the filesystem can not be created
+     */
+    @Override
+	public FileSystem createFileSystem(Session session) throws IOException {
+    	return null;
+    }
 }
diff --git a/src/main/java/com/gitblit/transport/ssh/FileKeyPairProvider.java b/src/main/java/com/gitblit/transport/ssh/FileKeyPairProvider.java
new file mode 100644
index 0000000..db0741e
--- /dev/null
+++ b/src/main/java/com/gitblit/transport/ssh/FileKeyPairProvider.java
@@ -0,0 +1,154 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.gitblit.transport.ssh;
+
+import java.io.FileInputStream;
+import java.io.InputStreamReader;
+import java.security.KeyPair;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+import org.apache.sshd.common.keyprovider.AbstractKeyPairProvider;
+import org.apache.sshd.common.util.SecurityUtils;
+import org.bouncycastle.openssl.PEMDecryptorProvider;
+import org.bouncycastle.openssl.PEMEncryptedKeyPair;
+import org.bouncycastle.openssl.PEMKeyPair;
+import org.bouncycastle.openssl.PEMParser;
+import org.bouncycastle.openssl.PasswordFinder;
+import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
+import org.bouncycastle.openssl.jcajce.JcePEMDecryptorProviderBuilder;
+
+/**
+ * This host key provider loads private keys from the specified files.
+ *
+ * Note that this class has a direct dependency on BouncyCastle and won't work
+ * unless it has been correctly registered as a security provider.
+ *
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public class FileKeyPairProvider extends AbstractKeyPairProvider {
+
+    private String[] files;
+    private PasswordFinder passwordFinder;
+
+    public FileKeyPairProvider() {
+    }
+
+    public FileKeyPairProvider(String[] files) {
+        this.files = files;
+    }
+
+    public FileKeyPairProvider(String[] files, PasswordFinder passwordFinder) {
+        this.files = files;
+        this.passwordFinder = passwordFinder;
+    }
+
+    public String[] getFiles() {
+        return files;
+    }
+
+    public void setFiles(String[] files) {
+        this.files = files;
+    }
+
+    public PasswordFinder getPasswordFinder() {
+        return passwordFinder;
+    }
+
+    public void setPasswordFinder(PasswordFinder passwordFinder) {
+        this.passwordFinder = passwordFinder;
+    }
+
+    public Iterable<KeyPair> loadKeys() {
+        if (!SecurityUtils.isBouncyCastleRegistered()) {
+            throw new IllegalStateException("BouncyCastle must be registered as a JCE provider");
+        }
+        return new Iterable<KeyPair>() {
+            @Override
+			public Iterator<KeyPair> iterator() {
+                return new Iterator<KeyPair>() {
+                    private final Iterator<String> iterator = Arrays.asList(files).iterator();
+                    private KeyPair nextKeyPair;
+                    private boolean nextKeyPairSet = false;
+                    @Override
+					public boolean hasNext() {
+                        return nextKeyPairSet || setNextObject();
+                    }
+                    @Override
+					public KeyPair next() {
+                        if (!nextKeyPairSet) {
+                            if (!setNextObject()) {
+                                throw new NoSuchElementException();
+                            }
+                        }
+                        nextKeyPairSet = false;
+                        return nextKeyPair;
+                    }
+                    @Override
+					public void remove() {
+                        throw new UnsupportedOperationException();
+                    }
+                    private boolean setNextObject() {
+                        while (iterator.hasNext()) {
+                            String file = iterator.next();
+                            nextKeyPair = doLoadKey(file);
+                            if (nextKeyPair != null) {
+                                nextKeyPairSet = true;
+                                return true;
+                            }
+                        }
+                        return false;
+                    }
+
+                };
+            }
+        };
+    }
+
+    protected KeyPair doLoadKey(String file) {
+        try {
+            PEMParser r = new PEMParser(new InputStreamReader(new FileInputStream(file)));
+            try {
+                Object o = r.readObject();
+
+                JcaPEMKeyConverter pemConverter = new JcaPEMKeyConverter();
+                pemConverter.setProvider("BC");
+                if (passwordFinder != null && o instanceof PEMEncryptedKeyPair) {
+                    JcePEMDecryptorProviderBuilder decryptorBuilder = new JcePEMDecryptorProviderBuilder();
+                    PEMDecryptorProvider pemDecryptor = decryptorBuilder.build(passwordFinder.getPassword());
+                    o = pemConverter.getKeyPair(((PEMEncryptedKeyPair) o).decryptKeyPair(pemDecryptor));
+                }
+
+                if (o instanceof PEMKeyPair) {
+                    o = pemConverter.getKeyPair((PEMKeyPair)o);
+                    return (KeyPair) o;
+                } else if (o instanceof KeyPair) {
+                    return (KeyPair) o;
+                }
+            } finally {
+                r.close();
+            }
+        } catch (Exception e) {
+            log.warn("Unable to read key " + file, e);
+        }
+        return null;
+    }
+
+}
diff --git a/src/main/java/com/gitblit/transport/ssh/NonForwardingFilter.java b/src/main/java/com/gitblit/transport/ssh/NonForwardingFilter.java
index 4bd75d5..29f7750 100644
--- a/src/main/java/com/gitblit/transport/ssh/NonForwardingFilter.java
+++ b/src/main/java/com/gitblit/transport/ssh/NonForwardingFilter.java
@@ -15,13 +15,14 @@
  */
 package com.gitblit.transport.ssh;
 
-import org.apache.sshd.common.ForwardingFilter;
-import org.apache.sshd.common.Session;
 import org.apache.sshd.common.SshdSocketAddress;
+import org.apache.sshd.common.session.Session;
+import org.apache.sshd.server.forward.ForwardingFilter;
 
 public class NonForwardingFilter implements ForwardingFilter {
+
 	@Override
-	public boolean canConnect(SshdSocketAddress address, Session session) {
+	public boolean canConnect(Type type, SshdSocketAddress address, Session session) {
 		return false;
 	}
 
diff --git a/src/main/java/com/gitblit/transport/ssh/SshDaemon.java b/src/main/java/com/gitblit/transport/ssh/SshDaemon.java
index 68a2e90..b6fae25 100644
--- a/src/main/java/com/gitblit/transport/ssh/SshDaemon.java
+++ b/src/main/java/com/gitblit/transport/ssh/SshDaemon.java
@@ -28,20 +28,19 @@
 import java.util.Locale;
 import java.util.concurrent.atomic.AtomicBoolean;
 
-import org.apache.sshd.SshServer;
 import org.apache.sshd.common.NamedFactory;
 import org.apache.sshd.common.io.IoServiceFactoryFactory;
 import org.apache.sshd.common.io.mina.MinaServiceFactoryFactory;
 import org.apache.sshd.common.io.nio2.Nio2ServiceFactoryFactory;
-import org.apache.sshd.common.keyprovider.FileKeyPairProvider;
 import org.apache.sshd.common.util.SecurityUtils;
-import org.apache.sshd.server.UserAuth;
+import org.apache.sshd.server.SshServer;
 import org.apache.sshd.server.auth.CachingPublicKeyAuthenticator;
-import org.apache.sshd.server.auth.UserAuthKeyboardInteractive;
-import org.apache.sshd.server.auth.UserAuthPassword;
-import org.apache.sshd.server.auth.UserAuthPublicKey;
+import org.apache.sshd.server.auth.UserAuth;
+import org.apache.sshd.server.auth.UserAuthKeyboardInteractiveFactory;
+import org.apache.sshd.server.auth.UserAuthPasswordFactory;
+import org.apache.sshd.server.auth.UserAuthPublicKeyFactory;
 import org.apache.sshd.server.auth.gss.GSSAuthenticator;
-import org.apache.sshd.server.auth.gss.UserAuthGSS;
+import org.apache.sshd.server.auth.gss.UserAuthGSSFactory;
 import org.bouncycastle.openssl.PEMWriter;
 import org.eclipse.jgit.internal.JGitText;
 import org.slf4j.Logger;
@@ -156,17 +155,17 @@
 			switch (authenticatorName) {
 			case "gssapi-with-mic":
 				if(gssAuthenticator != null) {
-					userAuthFactories.add(new UserAuthGSS.Factory());
+					userAuthFactories.add(new UserAuthGSSFactory());
 				}
 				break;
 			case "publickey":
-				userAuthFactories.add(new UserAuthPublicKey.Factory());
+				userAuthFactories.add(new UserAuthPublicKeyFactory());
 				break;
 			case "password":
-				userAuthFactories.add(new UserAuthPassword.Factory());
+				userAuthFactories.add(new UserAuthPasswordFactory());
 				break;
 			case "keyboard-interactive":
-				userAuthFactories.add(new UserAuthKeyboardInteractive.Factory());
+				userAuthFactories.add(new UserAuthKeyboardInteractiveFactory());
 				break;
 			default:
 				log.error("Unknown ssh authenticator: '{}'", authenticatorName);
@@ -257,7 +256,7 @@
 			try {
 				((SshCommandFactory) sshd.getCommandFactory()).stop();
 				sshd.stop();
-			} catch (InterruptedException e) {
+			} catch (IOException e) {
 				log.error("SSH Daemon stop interrupted", e);
 			}
 		}
diff --git a/src/main/java/com/gitblit/transport/ssh/SshDaemonClient.java b/src/main/java/com/gitblit/transport/ssh/SshDaemonClient.java
index a5d4c3d..af25251 100644
--- a/src/main/java/com/gitblit/transport/ssh/SshDaemonClient.java
+++ b/src/main/java/com/gitblit/transport/ssh/SshDaemonClient.java
@@ -17,7 +17,7 @@
 
 import java.net.SocketAddress;
 
-import org.apache.sshd.common.Session.AttributeKey;
+import org.apache.sshd.common.session.Session.AttributeKey;
 
 import com.gitblit.models.UserModel;
 
diff --git a/src/main/java/com/gitblit/transport/ssh/SshKey.java b/src/main/java/com/gitblit/transport/ssh/SshKey.java
index 9c99d1a..9fd1005 100644
--- a/src/main/java/com/gitblit/transport/ssh/SshKey.java
+++ b/src/main/java/com/gitblit/transport/ssh/SshKey.java
@@ -22,7 +22,8 @@
 
 import org.apache.commons.codec.binary.Base64;
 import org.apache.sshd.common.SshException;
-import org.apache.sshd.common.util.Buffer;
+import org.apache.sshd.common.util.buffer.Buffer;
+import org.apache.sshd.common.util.buffer.ByteArrayBuffer;
 import org.eclipse.jgit.lib.Constants;
 
 import com.gitblit.Constants.AccessPermission;
@@ -72,7 +73,7 @@
 			}
 			final byte[] bin = Base64.decodeBase64(Constants.encodeASCII(parts[1]));
 			try {
-				publicKey = new Buffer(bin).getRawPublicKey();
+				publicKey = new ByteArrayBuffer(bin).getRawPublicKey();
 			} catch (SshException e) {
 				throw new RuntimeException(e);
 			}
@@ -145,7 +146,7 @@
 	public String getRawData() {
 		if (rawData == null && publicKey != null) {
 			// build the raw data manually from the public key
-			Buffer buf = new Buffer();
+			Buffer buf = new ByteArrayBuffer();
 
 			// 1: identify the algorithm
 			buf.putRawPublicKey(publicKey);
diff --git a/src/main/java/com/gitblit/transport/ssh/SshKeyAuthenticator.java b/src/main/java/com/gitblit/transport/ssh/SshKeyAuthenticator.java
index c28a2ed..dc9d8a4 100644
--- a/src/main/java/com/gitblit/transport/ssh/SshKeyAuthenticator.java
+++ b/src/main/java/com/gitblit/transport/ssh/SshKeyAuthenticator.java
@@ -19,7 +19,7 @@
 import java.util.List;
 import java.util.Locale;
 
-import org.apache.sshd.server.PublickeyAuthenticator;
+import org.apache.sshd.server.auth.pubkey.PublickeyAuthenticator;
 import org.apache.sshd.server.session.ServerSession;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
diff --git a/src/main/java/com/gitblit/transport/ssh/SshServerSession.java b/src/main/java/com/gitblit/transport/ssh/SshServerSession.java
index d12a6be..02504ec 100644
--- a/src/main/java/com/gitblit/transport/ssh/SshServerSession.java
+++ b/src/main/java/com/gitblit/transport/ssh/SshServerSession.java
@@ -19,10 +19,10 @@
 import org.apache.sshd.common.future.SshFutureListener;
 import org.apache.sshd.common.io.IoSession;
 import org.apache.sshd.server.ServerFactoryManager;
-import org.apache.sshd.server.session.ServerSession;
+import org.apache.sshd.server.session.ServerSessionImpl;
 
 // Expose addition of close session listeners
-class SshServerSession extends ServerSession {
+class SshServerSession extends ServerSessionImpl {
 
 	SshServerSession(ServerFactoryManager server, IoSession ioSession) throws Exception {
 		super(server, ioSession);
diff --git a/src/main/java/com/gitblit/transport/ssh/SshServerSessionFactory.java b/src/main/java/com/gitblit/transport/ssh/SshServerSessionFactory.java
index 0c018f0..bc67cec 100644
--- a/src/main/java/com/gitblit/transport/ssh/SshServerSessionFactory.java
+++ b/src/main/java/com/gitblit/transport/ssh/SshServerSessionFactory.java
@@ -67,6 +67,6 @@
 
 	@Override
 	protected AbstractSession doCreateSession(IoSession ioSession) throws Exception {
-		return new SshServerSession(server, ioSession);
+		return new SshServerSession(getServer(), ioSession);
 	}
 }
diff --git a/src/main/java/com/gitblit/transport/ssh/UsernamePasswordAuthenticator.java b/src/main/java/com/gitblit/transport/ssh/UsernamePasswordAuthenticator.java
index d7c4fe5..a6d77ec 100644
--- a/src/main/java/com/gitblit/transport/ssh/UsernamePasswordAuthenticator.java
+++ b/src/main/java/com/gitblit/transport/ssh/UsernamePasswordAuthenticator.java
@@ -17,7 +17,7 @@
 
 import java.util.Locale;
 
-import org.apache.sshd.server.PasswordAuthenticator;
+import org.apache.sshd.server.auth.password.PasswordAuthenticator;
 import org.apache.sshd.server.session.ServerSession;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
diff --git a/src/test/java/com/gitblit/tests/SshDaemonTest.java b/src/test/java/com/gitblit/tests/SshDaemonTest.java
index dcaeaff..c5deb7d 100644
--- a/src/test/java/com/gitblit/tests/SshDaemonTest.java
+++ b/src/test/java/com/gitblit/tests/SshDaemonTest.java
@@ -19,8 +19,8 @@
 import java.text.MessageFormat;
 import java.util.List;
 
-import org.apache.sshd.ClientSession;
-import org.apache.sshd.SshClient;
+import org.apache.sshd.client.SshClient;
+import org.apache.sshd.client.session.ClientSession;
 import org.eclipse.jgit.api.CloneCommand;
 import org.eclipse.jgit.api.Git;
 import org.eclipse.jgit.revwalk.RevCommit;
diff --git a/src/test/java/com/gitblit/tests/SshUnitTest.java b/src/test/java/com/gitblit/tests/SshUnitTest.java
index 3def700..453f304 100644
--- a/src/test/java/com/gitblit/tests/SshUnitTest.java
+++ b/src/test/java/com/gitblit/tests/SshUnitTest.java
@@ -28,14 +28,14 @@
 import java.util.List;
 import java.util.concurrent.atomic.AtomicBoolean;
 
-import org.apache.sshd.ClientChannel;
-import org.apache.sshd.ClientSession;
-import org.apache.sshd.SshClient;
 import org.apache.sshd.client.ServerKeyVerifier;
+import org.apache.sshd.client.SshClient;
+import org.apache.sshd.client.auth.UserAuth;
+import org.apache.sshd.client.auth.UserAuthPublicKeyFactory;
+import org.apache.sshd.client.channel.ClientChannel;
+import org.apache.sshd.client.session.ClientSession;
 import org.apache.sshd.common.NamedFactory;
 import org.apache.sshd.common.util.SecurityUtils;
-import org.apache.sshd.client.UserAuth;
-import org.apache.sshd.client.auth.UserAuthPublicKey;
 import org.junit.After;
 import org.junit.AfterClass;
 import org.junit.Before;
@@ -108,7 +108,7 @@
 			}
 		});
 		List<NamedFactory<UserAuth>> userAuthFactories = new ArrayList<>();
-		userAuthFactories.add(new UserAuthPublicKey.Factory());
+		userAuthFactories.add(new UserAuthPublicKeyFactory());
 		client.setUserAuthFactories(userAuthFactories);
 		client.start();
 		return client;

--
Gitblit v1.9.1