James Moger
2015-10-05 92ae83de6b4f5401a1007bbb26e2f01168e9d6cb
Revert manual specification of ssh user auth factories
7 files modified
127 ■■■■ changed files
src/main/distrib/data/defaults.properties 20 ●●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/transport/ssh/SshDaemon.java 57 ●●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/transport/ssh/SshKrbAuthenticator.java 26 ●●●● patch | view | raw | blame | history
src/test/config/test-gitblit.properties 2 ●●●●● patch | view | raw | blame | history
src/test/java/com/gitblit/tests/JschConfigTestSessionFactory.java 1 ●●●● patch | view | raw | blame | history
src/test/java/com/gitblit/tests/SshKerberosAuthenticationTest.java 13 ●●●●● patch | view | raw | blame | history
src/test/java/com/gitblit/tests/SshUnitTest.java 8 ●●●●● patch | view | raw | blame | history
src/main/distrib/data/defaults.properties
@@ -138,27 +138,21 @@
# SINCE 1.5.0
git.sshKeysFolder= ${baseFolder}/ssh
# Use kerberos5 (GSS) authentication
# Use Kerberos5 (GSS) authentication
#
# SINCE 1.7.0
git.sshWithKrb5 = "false"
git.sshWithKrb5 = false
# The path to a kerberos 5 keytab.
# The path to a Kerberos 5 keytab.
#
# SINCE 1.7.0
git.sshKrb5Keytab = ""
git.sshKrb5Keytab =
# The service principal name to be used for Kerberos5.  The default is host/hostname.
# The service principal name to be used for Kerberos5.
# The default is host/hostname.
#
# SINCE 1.7.0
git.sshKrb5ServicePrincipalName = ""
# A comma-separated list of authentication method. They will be tried in
# the given order. Possible values are
# "gssapi-with-mic", "publickey", "keyboard-interactive" or "password"
#
# SINCE 1.7.0
git.sshAuthenticatorsOrder = "password,keyboard-interactive,publickey"
git.sshKrb5ServicePrincipalName =
# SSH backend NIO2|MINA.
#
src/main/java/com/gitblit/transport/ssh/SshDaemon.java
@@ -23,24 +23,14 @@
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.concurrent.atomic.AtomicBoolean;
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.util.SecurityUtils;
import org.apache.sshd.server.SshServer;
import org.apache.sshd.server.auth.CachingPublicKeyAuthenticator;
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.UserAuthGSSFactory;
import org.bouncycastle.openssl.PEMWriter;
import org.eclipse.jgit.internal.JGitText;
import org.slf4j.Logger;
@@ -130,48 +120,6 @@
            addr = new InetSocketAddress(bindInterface, port);
        }
        //Will do GSS ?
        GSSAuthenticator gssAuthenticator = null;
        if(settings.getBoolean(Keys.git.sshWithKrb5, false)) {
            gssAuthenticator = new SshKrbAuthenticator(gitblit);
            String keytabString = settings.getString(Keys.git.sshKrb5Keytab,
                    "");
            if(! keytabString.isEmpty()) {
                gssAuthenticator.setKeytabFile(keytabString);
            }
            String servicePrincipalName = settings.getString(Keys.git.sshKrb5ServicePrincipalName,
                    "");
            if(! servicePrincipalName.isEmpty()) {
                gssAuthenticator.setServicePrincipalName(servicePrincipalName);
            }
        }
        //Sort the authenticators for sshd
        List<NamedFactory<UserAuth>> userAuthFactories = new ArrayList<>();
        String sshAuthenticatorsOrderString = settings.getString(Keys.git.sshAuthenticatorsOrder,
                "password,keyboard-interactive,publickey");
        for(String authenticator: sshAuthenticatorsOrderString.split(",")) {
            String authenticatorName = authenticator.trim().toLowerCase(Locale.US);
            switch (authenticatorName) {
            case "gssapi-with-mic":
                if(gssAuthenticator != null) {
                    userAuthFactories.add(new UserAuthGSSFactory());
                }
                break;
            case "publickey":
                userAuthFactories.add(new UserAuthPublicKeyFactory());
                break;
            case "password":
                userAuthFactories.add(new UserAuthPasswordFactory());
                break;
            case "keyboard-interactive":
                userAuthFactories.add(new UserAuthKeyboardInteractiveFactory());
                break;
            default:
                log.error("Unknown ssh authenticator: '{}'", authenticatorName);
            }
        }
        // Create the SSH server
        sshd = SshServer.setUpDefaultServer();
        sshd.setPort(addr.getPort());
@@ -179,10 +127,9 @@
        sshd.setKeyPairProvider(hostKeyPairProvider);
        sshd.setPublickeyAuthenticator(new CachingPublicKeyAuthenticator(keyAuthenticator));
        sshd.setPasswordAuthenticator(new UsernamePasswordAuthenticator(gitblit));
        if(gssAuthenticator != null) {
            sshd.setGSSAuthenticator(gssAuthenticator);
        if (settings.getBoolean(Keys.git.sshWithKrb5, false)) {
            sshd.setGSSAuthenticator(new SshKrbAuthenticator(settings, gitblit));
        }
        sshd.setUserAuthFactories(userAuthFactories);
        sshd.setSessionFactory(new SshServerSessionFactory());
        sshd.setFileSystemFactory(new DisabledFilesystemFactory());
        sshd.setTcpipForwardingFilter(new NonForwardingFilter());
src/main/java/com/gitblit/transport/ssh/SshKrbAuthenticator.java
@@ -15,27 +15,41 @@
 */
package com.gitblit.transport.ssh;
import com.gitblit.manager.IAuthenticationManager;
import com.gitblit.models.UserModel;
import java.util.Locale;
import org.apache.sshd.server.auth.gss.GSSAuthenticator;
import org.apache.sshd.server.session.ServerSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.gitblit.IStoredSettings;
import com.gitblit.Keys;
import com.gitblit.manager.IAuthenticationManager;
import com.gitblit.models.UserModel;
public class SshKrbAuthenticator extends GSSAuthenticator {
    protected final Logger log = LoggerFactory.getLogger(getClass());
    protected final IAuthenticationManager authManager;
    public SshKrbAuthenticator(IAuthenticationManager authManager) {
    public SshKrbAuthenticator(IStoredSettings settings, IAuthenticationManager authManager) {
        this.authManager = authManager;
        log.info("registry  {}", authManager);
        String keytabString = settings.getString(Keys.git.sshKrb5Keytab, "");
        if(! keytabString.isEmpty()) {
            setKeytabFile(keytabString);
        }
        String servicePrincipalName = settings.getString(Keys.git.sshKrb5ServicePrincipalName, "");
        if(! servicePrincipalName.isEmpty()) {
            setServicePrincipalName(servicePrincipalName);
        }
    }
    @Override
    public boolean validateIdentity(ServerSession session, String identity) {
        log.info("identify with kerberos {}", identity);
        SshDaemonClient client = (SshDaemonClient)session.getAttribute(SshDaemonClient.KEY);
        SshDaemonClient client = session.getAttribute(SshDaemonClient.KEY);
        if (client.getUser() != null) {
            log.info("{} has already authenticated!", identity);
            return true;
src/test/config/test-gitblit.properties
@@ -9,8 +9,6 @@
git.daemonPort = 8300
git.sshPort = 29418
git.sshKeysManager = com.gitblit.transport.ssh.MemoryKeyManager
git.sshWithKrb5 = true
git.sshAuthenticatorsOrder = password, publickey,gssapi-with-mic,invalid
groovy.scriptsFolder = src/main/distrib/data/groovy
groovy.preReceiveScripts = blockpush
groovy.postReceiveScripts = sendmail
src/test/java/com/gitblit/tests/JschConfigTestSessionFactory.java
@@ -21,7 +21,6 @@
    @Override
    protected void configure(OpenSshConfig.Host host, Session session) {
        session.setConfig("StrictHostKeyChecking", "no");
        session.setConfig("PreferredAuthentications", "password");
    }
    @Override
src/test/java/com/gitblit/tests/SshKerberosAuthenticationTest.java
@@ -27,6 +27,7 @@
import com.gitblit.manager.IRuntimeManager;
import com.gitblit.manager.IUserManager;
import com.gitblit.models.UserModel;
import com.gitblit.tests.mock.MemorySettings;
import com.gitblit.transport.ssh.SshDaemonClient;
import com.gitblit.transport.ssh.SshKrbAuthenticator;
@@ -39,20 +40,21 @@
    @Test
    public void testUserManager() {
        IRuntimeManager rm = Mockito.mock(IRuntimeManager.class);
        //Build an UserManager that can build a UserModel
        IUserManager im = Mockito.mock(IUserManager.class);
        Mockito.doAnswer(new Answer<Object>() {
            @Override
            public Object answer(InvocationOnMock invocation) {
                Object[] args = invocation.getArguments();
                String user = (String) args[0];
                return new UserModel(user);
            }
            }
        }).when(im).getUserModel(Mockito.anyString());
        AuthenticationManager am = new AuthenticationManager(rm, im);
        GSSAuthenticator gssAuthenticator = new SshKrbAuthenticator(am);
        GSSAuthenticator gssAuthenticator = new SshKrbAuthenticator(new MemorySettings(), am);
        ServerSession session = Mockito.mock(ServerSession.class);
@@ -61,12 +63,13 @@
        SshDaemonClient client = Mockito.mock(SshDaemonClient.class);
        Mockito.when(client.getUser()).thenReturn(umw.um);
        Mockito.doAnswer(new Answer<Object>() {
            @Override
            public Object answer(InvocationOnMock invocation) {
                Object[] args = invocation.getArguments();
                UserModel um = (UserModel) args[0];
                umw.um = um;
                return null;
            }
            }
        }).when(client).setUser(Mockito.any(UserModel.class));
        Mockito.when(session.getAttribute(SshDaemonClient.KEY)).thenReturn(client);
src/test/java/com/gitblit/tests/SshUnitTest.java
@@ -24,17 +24,12 @@
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PublicKey;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
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.junit.After;
import org.junit.AfterClass;
@@ -107,9 +102,6 @@
                return true;
            }
        });
        List<NamedFactory<UserAuth>> userAuthFactories = new ArrayList<>();
        userAuthFactories.add(new UserAuthPublicKeyFactory());
        client.setUserAuthFactories(userAuthFactories);
        client.start();
        return client;
    }