@@ -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" /> |
@@ -111,7 +111,7 @@ properties: { | |||
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 |
@@ -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> |
@@ -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; | |||
} | |||
} |
@@ -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; | |||
} | |||
} |
@@ -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; | |||
} | |||
@@ -28,20 +28,19 @@ import java.util.List; | |||
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 @@ public class SshDaemon { | |||
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 @@ public class SshDaemon { | |||
try { | |||
((SshCommandFactory) sshd.getCommandFactory()).stop(); | |||
sshd.stop(); | |||
} catch (InterruptedException e) { | |||
} catch (IOException e) { | |||
log.error("SSH Daemon stop interrupted", e); | |||
} | |||
} |
@@ -17,7 +17,7 @@ package com.gitblit.transport.ssh; | |||
import java.net.SocketAddress; | |||
import org.apache.sshd.common.Session.AttributeKey; | |||
import org.apache.sshd.common.session.Session.AttributeKey; | |||
import com.gitblit.models.UserModel; | |||
@@ -22,7 +22,8 @@ import java.util.List; | |||
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 @@ public class SshKey implements Serializable { | |||
} | |||
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 class SshKey implements Serializable { | |||
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); |
@@ -19,7 +19,7 @@ import java.security.PublicKey; | |||
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; |
@@ -19,10 +19,10 @@ import org.apache.sshd.common.future.CloseFuture; | |||
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); |
@@ -67,6 +67,6 @@ public class SshServerSessionFactory extends SessionFactory { | |||
@Override | |||
protected AbstractSession doCreateSession(IoSession ioSession) throws Exception { | |||
return new SshServerSession(server, ioSession); | |||
return new SshServerSession(getServer(), ioSession); | |||
} | |||
} |
@@ -17,7 +17,7 @@ package com.gitblit.transport.ssh; | |||
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; |
@@ -19,8 +19,8 @@ import java.io.File; | |||
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; |
@@ -28,14 +28,14 @@ import java.util.ArrayList; | |||
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 @@ public abstract class SshUnitTest extends GitblitUnitTest { | |||
} | |||
}); | |||
List<NamedFactory<UserAuth>> userAuthFactories = new ArrayList<>(); | |||
userAuthFactories.add(new UserAuthPublicKey.Factory()); | |||
userAuthFactories.add(new UserAuthPublicKeyFactory()); | |||
client.setUserAuthFactories(userAuthFactories); | |||
client.start(); | |||
return client; |