.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;