James Moger
2015-09-18 d41034ad2ff334707a58ace5f3cd1de5fcfa1815
Update to SSHD 1.0.0
1 files added
14 files modified
264 ■■■■ changed files
.classpath 2 ●●● patch | view | raw | blame | history
build.moxie 2 ●●● patch | view | raw | blame | history
gitblit.iml 6 ●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/transport/ssh/DisabledFilesystemFactory.java 35 ●●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/transport/ssh/FileKeyPairProvider.java 154 ●●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/transport/ssh/NonForwardingFilter.java 7 ●●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/transport/ssh/SshDaemon.java 23 ●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/transport/ssh/SshDaemonClient.java 2 ●●● patch | view | raw | blame | history
src/main/java/com/gitblit/transport/ssh/SshKey.java 7 ●●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/transport/ssh/SshKeyAuthenticator.java 2 ●●● patch | view | raw | blame | history
src/main/java/com/gitblit/transport/ssh/SshServerSession.java 4 ●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/transport/ssh/SshServerSessionFactory.java 2 ●●● patch | view | raw | blame | history
src/main/java/com/gitblit/transport/ssh/UsernamePasswordAuthenticator.java 2 ●●● patch | view | raw | blame | history
src/test/java/com/gitblit/tests/SshDaemonTest.java 4 ●●●● patch | view | raw | blame | history
src/test/java/com/gitblit/tests/SshUnitTest.java 12 ●●●● patch | view | raw | blame | history
.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" />
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
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>
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;
    }
}
src/main/java/com/gitblit/transport/ssh/FileKeyPairProvider.java
New file
@@ -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;
    }
}
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;
    }
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);
            }
        }
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;
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);
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;
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);
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);
    }
}
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;
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;
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;