James Moger
2014-03-17 245836904ba5cecdc31773cf7c9616396c8ad8c0
Elevate the public key manager to a top-level manager
1 files added
1 files renamed
18 files modified
1 files deleted
437 ■■■■ changed files
src/main/distrib/data/gitblit.properties 5 ●●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/DaggerModule.java 37 ●●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/FederationClient.java 2 ●●● patch | view | raw | blame | history
src/main/java/com/gitblit/GitBlit.java 5 ●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/manager/GitblitManager.java 10 ●●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/manager/IGitblit.java 8 ●●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/servlet/GitblitContext.java 4 ●●● patch | view | raw | blame | history
src/main/java/com/gitblit/transport/ssh/CachingPublicKeyAuthenticator.java 15 ●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/transport/ssh/FileKeyManager.java 5 ●●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/transport/ssh/IPublicKeyManager.java 10 ●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/transport/ssh/MemoryKeyManager.java 98 ●●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/transport/ssh/NullKeyManager.java 5 ●●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/transport/ssh/SshCommandFactory.java 8 ●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/transport/ssh/SshDaemon.java 107 ●●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/transport/ssh/commands/DispatchCommand.java 13 ●●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/transport/ssh/gitblit/BaseKeyCommand.java 12 ●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/wicket/GitBlitWebApp.java 9 ●●●●● patch | view | raw | blame | history
src/test/config/test-gitblit.properties 2 ●●● patch | view | raw | blame | history
src/test/java/com/gitblit/tests/BogusPublicKeyAuthenticator.java 39 ●●●●● patch | view | raw | blame | history
src/test/java/com/gitblit/tests/GitBlitSuite.java 18 ●●●● patch | view | raw | blame | history
src/test/java/com/gitblit/tests/SshDaemonTest.java 25 ●●●●● patch | view | raw | blame | history
src/main/distrib/data/gitblit.properties
@@ -129,11 +129,6 @@
# SINCE 1.5.0
git.sshBackend = NIO2
# SSH public key authenticator
#
# SINCE 1.5.0
git.sshPublicKeyAuthenticator = com.gitblit.transport.ssh.CachingPublicKeyAuthenticator
# Allow push/pull over http/https with JGit servlet.
# If you do NOT want to allow Git clients to clone/push to Gitblit set this
# to false.  You might want to do this if you are only using ssh:// or git://.
src/main/java/com/gitblit/DaggerModule.java
@@ -32,6 +32,11 @@
import com.gitblit.manager.RepositoryManager;
import com.gitblit.manager.RuntimeManager;
import com.gitblit.manager.UserManager;
import com.gitblit.transport.ssh.FileKeyManager;
import com.gitblit.transport.ssh.IPublicKeyManager;
import com.gitblit.transport.ssh.MemoryKeyManager;
import com.gitblit.transport.ssh.NullKeyManager;
import com.gitblit.utils.StringUtils;
import com.gitblit.wicket.GitBlitWebApp;
import dagger.Module;
@@ -53,6 +58,7 @@
            INotificationManager.class,
            IUserManager.class,
            IAuthenticationManager.class,
            IPublicKeyManager.class,
            IRepositoryManager.class,
            IProjectManager.class,
            IFederationManager.class,
@@ -62,7 +68,7 @@
            // the Gitblit Wicket app
            GitBlitWebApp.class
    }
        }
)
public class DaggerModule {
@@ -89,6 +95,31 @@
        return new AuthenticationManager(
                runtimeManager,
                userManager);
    }
    @Provides @Singleton IPublicKeyManager providePublicKeyManager(
            IStoredSettings settings,
            IRuntimeManager runtimeManager) {
        String clazz = settings.getString(Keys.git.sshKeysManager, FileKeyManager.class.getName());
        if (StringUtils.isEmpty(clazz)) {
            clazz = FileKeyManager.class.getName();
        }
        if (FileKeyManager.class.getName().equals(clazz)) {
            return new FileKeyManager(runtimeManager);
        } else if (NullKeyManager.class.getName().equals(clazz)) {
            return new NullKeyManager();
        } else if (MemoryKeyManager.class.getName().equals(clazz)) {
            return new MemoryKeyManager();
        } else {
            try {
                Class<?> mgrClass = Class.forName(clazz);
                return (IPublicKeyManager) mgrClass.newInstance();
            } catch (Exception e) {
            }
            return null;
        }
    }
    @Provides @Singleton IRepositoryManager provideRepositoryManager(
@@ -127,6 +158,7 @@
            INotificationManager notificationManager,
            IUserManager userManager,
            IAuthenticationManager authenticationManager,
            IPublicKeyManager publicKeyManager,
            IRepositoryManager repositoryManager,
            IProjectManager projectManager,
            IFederationManager federationManager) {
@@ -136,6 +168,7 @@
                notificationManager,
                userManager,
                authenticationManager,
                publicKeyManager,
                repositoryManager,
                projectManager,
                federationManager);
@@ -146,6 +179,7 @@
            INotificationManager notificationManager,
            IUserManager userManager,
            IAuthenticationManager authenticationManager,
            IPublicKeyManager publicKeyManager,
            IRepositoryManager repositoryManager,
            IProjectManager projectManager,
            IFederationManager federationManager,
@@ -156,6 +190,7 @@
                notificationManager,
                userManager,
                authenticationManager,
                publicKeyManager,
                repositoryManager,
                projectManager,
                federationManager,
src/main/java/com/gitblit/FederationClient.java
@@ -97,7 +97,7 @@
        UserManager users = new UserManager(runtime).start();
        RepositoryManager repositories = new RepositoryManager(runtime, users).start();
        FederationManager federation = new FederationManager(runtime, notifications, repositories).start();
        IGitblit gitblit = new GitblitManager(runtime, notifications, users, null, repositories, null, federation);
        IGitblit gitblit = new GitblitManager(runtime, notifications, users, null, null, repositories, null, federation);
        FederationPullService puller = new FederationPullService(gitblit, federation.getFederationRegistrations()) {
            @Override
src/main/java/com/gitblit/GitBlit.java
@@ -41,6 +41,7 @@
import com.gitblit.tickets.ITicketService;
import com.gitblit.tickets.NullTicketService;
import com.gitblit.tickets.RedisTicketService;
import com.gitblit.transport.ssh.IPublicKeyManager;
import com.gitblit.utils.StringUtils;
import dagger.Module;
@@ -67,6 +68,7 @@
            INotificationManager notificationManager,
            IUserManager userManager,
            IAuthenticationManager authenticationManager,
            IPublicKeyManager publicKeyManager,
            IRepositoryManager repositoryManager,
            IProjectManager projectManager,
            IFederationManager federationManager) {
@@ -75,6 +77,7 @@
                notificationManager,
                userManager,
                authenticationManager,
                publicKeyManager,
                repositoryManager,
                projectManager,
                federationManager);
@@ -262,7 +265,7 @@
                    FileTicketService.class,
                    BranchTicketService.class,
                    RedisTicketService.class
            }
                }
            )
    class GitBlitModule {
src/main/java/com/gitblit/manager/GitblitManager.java
@@ -69,6 +69,7 @@
import com.gitblit.models.TeamModel;
import com.gitblit.models.UserModel;
import com.gitblit.tickets.ITicketService;
import com.gitblit.transport.ssh.IPublicKeyManager;
import com.gitblit.utils.ArrayUtils;
import com.gitblit.utils.HttpUtils;
import com.gitblit.utils.JsonUtils;
@@ -107,6 +108,8 @@
    protected final IAuthenticationManager authenticationManager;
    protected final IPublicKeyManager publicKeyManager;
    protected final IRepositoryManager repositoryManager;
    protected final IProjectManager projectManager;
@@ -118,6 +121,7 @@
            INotificationManager notificationManager,
            IUserManager userManager,
            IAuthenticationManager authenticationManager,
            IPublicKeyManager publicKeyManager,
            IRepositoryManager repositoryManager,
            IProjectManager projectManager,
            IFederationManager federationManager) {
@@ -127,6 +131,7 @@
        this.notificationManager = notificationManager;
        this.userManager = userManager;
        this.authenticationManager = authenticationManager;
        this.publicKeyManager = publicKeyManager;
        this.repositoryManager = repositoryManager;
        this.projectManager = projectManager;
        this.federationManager = federationManager;
@@ -524,6 +529,11 @@
        throw new RuntimeException("This class does not have a ticket service!");
    }
    @Override
    public IPublicKeyManager getPublicKeyManager() {
        return publicKeyManager;
    }
    /*
     * ISTOREDSETTINGS
     *
src/main/java/com/gitblit/manager/IGitblit.java
@@ -27,6 +27,7 @@
import com.gitblit.models.TeamModel;
import com.gitblit.models.UserModel;
import com.gitblit.tickets.ITicketService;
import com.gitblit.transport.ssh.IPublicKeyManager;
public interface IGitblit extends IManager,
                                    IRuntimeManager,
@@ -109,4 +110,11 @@
     */
    ITicketService getTicketService();
    /**
     * Returns the SSH public key manager.
     *
     * @return the SSH public key manager
     */
    IPublicKeyManager getPublicKeyManager();
}
src/main/java/com/gitblit/servlet/GitblitContext.java
@@ -47,6 +47,7 @@
import com.gitblit.manager.IRepositoryManager;
import com.gitblit.manager.IRuntimeManager;
import com.gitblit.manager.IUserManager;
import com.gitblit.transport.ssh.IPublicKeyManager;
import com.gitblit.utils.ContainerUtils;
import com.gitblit.utils.StringUtils;
@@ -149,7 +150,7 @@
            String contextRealPath = context.getRealPath("/");
            File contextFolder = (contextRealPath != null) ? new File(contextRealPath) : null;
            // if the base folder dosen't match the default assume they don't want to use express,
            // if the base folder dosen't match the default assume they don't want to use express,
            // this allows for other containers to customise the basefolder per context.
            String defaultBase = Constants.contextFolder$ + "/WEB-INF/data";
            String base = lookupBaseFolderFromJndi();
@@ -178,6 +179,7 @@
        startManager(injector, INotificationManager.class);
        startManager(injector, IUserManager.class);
        startManager(injector, IAuthenticationManager.class);
        startManager(injector, IPublicKeyManager.class);
        startManager(injector, IRepositoryManager.class);
        startManager(injector, IProjectManager.class);
        startManager(injector, IFederationManager.class);
src/main/java/com/gitblit/transport/ssh/CachingPublicKeyAuthenticator.java
@@ -34,23 +34,23 @@
import com.google.common.base.Preconditions;
/**
 *
 *
 * @author Eric Myrhe
 *
 *
 */
public class CachingPublicKeyAuthenticator implements PublickeyAuthenticator,
        SessionListener {
    protected final Logger log = LoggerFactory.getLogger(getClass());
    protected final IKeyManager keyManager;
    protected final IPublicKeyManager keyManager;
    protected final IAuthenticationManager authManager;
    private final Map<ServerSession, Map<PublicKey, Boolean>> cache =
            new ConcurrentHashMap<ServerSession, Map<PublicKey, Boolean>>();
    public CachingPublicKeyAuthenticator(IKeyManager keyManager,
    public CachingPublicKeyAuthenticator(IPublicKeyManager keyManager,
            IAuthenticationManager authManager) {
        this.keyManager = keyManager;
        this.authManager = authManager;
@@ -101,16 +101,15 @@
        return false;
    }
    public IKeyManager getKeyManager() {
        return keyManager;
    }
    @Override
    public void sessionCreated(Session session) {
    }
    @Override
    public void sessionEvent(Session sesssion, Event event) {
    }
    @Override
    public void sessionClosed(Session session) {
        cache.remove(session);
    }
src/main/java/com/gitblit/transport/ssh/FileKeyManager.java
@@ -35,12 +35,12 @@
import com.google.common.io.Files;
/**
 * Manages SSH keys on the filesystem.
 * Manages public keys on the filesystem.
 *
 * @author James Moger
 *
 */
public class FileKeyManager extends IKeyManager {
public class FileKeyManager extends IPublicKeyManager {
    protected final IRuntimeManager runtimeManager;
@@ -59,6 +59,7 @@
    @Override
    public FileKeyManager start() {
        log.info(toString());
        return this;
    }
src/main/java/com/gitblit/transport/ssh/IPublicKeyManager.java
File was renamed from src/main/java/com/gitblit/transport/ssh/IKeyManager.java
@@ -24,16 +24,18 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.gitblit.manager.IManager;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
/**
 * Parent class for public key managers.
 *
 * @author James Moger
 *
 */
public abstract class IKeyManager {
public abstract class IPublicKeyManager implements IManager {
    protected final Logger log = LoggerFactory.getLogger(getClass());
@@ -48,11 +50,13 @@
                }
            });
    public abstract IKeyManager start();
    @Override
    public abstract IPublicKeyManager start();
    public abstract boolean isReady();
    public abstract IKeyManager stop();
    @Override
    public abstract IPublicKeyManager stop();
    public final List<PublicKey> getKeys(String username) {
        try {
src/main/java/com/gitblit/transport/ssh/MemoryKeyManager.java
New file
@@ -0,0 +1,98 @@
/*
 * Copyright 2014 gitblit.com.
 *
 * Licensed 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.security.PublicKey;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
 * Memory public key manager.
 *
 * @author James Moger
 *
 */
public class MemoryKeyManager extends IPublicKeyManager {
    Map<String, List<PublicKey>> keys;
    public MemoryKeyManager() {
        keys = new HashMap<String, List<PublicKey>>();
    }
    @Override
    public String toString() {
        return getClass().getSimpleName();
    }
    @Override
    public MemoryKeyManager start() {
        log.info(toString());
        return this;
    }
    @Override
    public boolean isReady() {
        return true;
    }
    @Override
    public MemoryKeyManager stop() {
        return this;
    }
    @Override
    protected boolean isStale(String username) {
        return false;
    }
    @Override
    protected List<PublicKey> getKeysImpl(String username) {
        String id = username.toLowerCase();
        if (keys.containsKey(id)) {
            return keys.get(id);
        }
        return null;
    }
    @Override
    public boolean addKey(String username, String data) {
        return false;
    }
    @Override
    public boolean removeKey(String username, String data) {
        return false;
    }
    @Override
    public boolean removeAllKeys(String username) {
        String id = username.toLowerCase();
        keys.remove(id.toLowerCase());
        return true;
    }
    /* Test method for populating the memory key manager */
    public void addKey(String username, PublicKey key) {
        String id = username.toLowerCase();
        if (!keys.containsKey(id)) {
            keys.put(id, new ArrayList<PublicKey>());
        }
        keys.get(id).add(key);
    }
}
src/main/java/com/gitblit/transport/ssh/NullKeyManager.java
@@ -19,12 +19,12 @@
import java.util.List;
/**
 * Rejects all SSH key management requests.
 * Rejects all public key management requests.
 *
 * @author James Moger
 *
 */
public class NullKeyManager extends IKeyManager {
public class NullKeyManager extends IPublicKeyManager {
    public NullKeyManager() {
    }
@@ -36,6 +36,7 @@
    @Override
    public NullKeyManager start() {
        log.info(toString());
        return this;
    }
src/main/java/com/gitblit/transport/ssh/SshCommandFactory.java
@@ -52,14 +52,10 @@
    private static final Logger logger = LoggerFactory.getLogger(SshCommandFactory.class);
    private final IGitblit gitblit;
    private final CachingPublicKeyAuthenticator keyAuthenticator;
    private final ScheduledExecutorService startExecutor;
    public SshCommandFactory(IGitblit gitblit,
            CachingPublicKeyAuthenticator keyAuthenticator,
            IdGenerator idGenerator) {
    public SshCommandFactory(IGitblit gitblit, IdGenerator idGenerator) {
        this.gitblit = gitblit;
        this.keyAuthenticator = keyAuthenticator;
        int threads = 2;// cfg.getInt("sshd","commandStartThreads", 2);
        WorkQueue workQueue = new WorkQueue(idGenerator);
@@ -83,8 +79,6 @@
        // TODO convert these dispatchers to plugin extension points
        root.registerDispatcher(user, GitblitDispatchCommand.class);
        root.registerDispatcher(user, GitDispatchCommand.class);
        root.setAuthenticator(keyAuthenticator);
        return root;
    }
src/main/java/com/gitblit/transport/ssh/SshDaemon.java
@@ -21,8 +21,6 @@
import java.text.MessageFormat;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.inject.Singleton;
import org.apache.sshd.SshServer;
import org.apache.sshd.common.io.IoServiceFactoryFactory;
import org.apache.sshd.common.io.mina.MinaServiceFactoryFactory;
@@ -35,14 +33,9 @@
import com.gitblit.Constants;
import com.gitblit.IStoredSettings;
import com.gitblit.Keys;
import com.gitblit.manager.IAuthenticationManager;
import com.gitblit.manager.IGitblit;
import com.gitblit.utils.IdGenerator;
import com.gitblit.utils.StringUtils;
import dagger.Module;
import dagger.ObjectGraph;
import dagger.Provides;
/**
 * Manager for the ssh transport. Roughly analogous to the
@@ -73,7 +66,6 @@
    private final IGitblit gitblit;
    private final SshServer sshd;
    private final ObjectGraph injector;
    /**
     * Construct the Gitblit SSH daemon.
@@ -82,14 +74,11 @@
     */
    public SshDaemon(IGitblit gitblit, IdGenerator idGenerator) {
        this.gitblit = gitblit;
        this.injector = ObjectGraph.create(new SshModule());
        IStoredSettings settings = gitblit.getSettings();
        int port = settings.getInteger(Keys.git.sshPort, 0);
        String bindInterface = settings.getString(Keys.git.sshBindInterface,
                "localhost");
        IKeyManager keyManager = getKeyManager();
        String sshBackendStr = settings.getString(Keys.git.sshBackend,
                SshSessionBackend.NIO2.name());
@@ -108,7 +97,7 @@
        File hostKeyStore = new File(gitblit.getBaseFolder(), HOST_KEY_STORE);
        CachingPublicKeyAuthenticator keyAuthenticator =
                getPublicKeyAuthenticator(keyManager, gitblit);
                new CachingPublicKeyAuthenticator(gitblit.getPublicKeyManager(), gitblit);
        sshd = SshServer.setUpDefaultServer();
        sshd.setPort(addr.getPort());
@@ -119,34 +108,13 @@
        sshd.setSessionFactory(new SshServerSessionFactory());
        sshd.setFileSystemFactory(new DisabledFilesystemFactory());
        sshd.setTcpipForwardingFilter(new NonForwardingFilter());
        sshd.setCommandFactory(new SshCommandFactory(gitblit, keyAuthenticator, idGenerator));
        sshd.setCommandFactory(new SshCommandFactory(gitblit, idGenerator));
        sshd.setShellFactory(new WelcomeShell(settings));
        String version = Constants.getGitBlitVersion() + " (" + sshd.getVersion() + ")";
        sshd.getProperties().put(SshServer.SERVER_IDENTIFICATION, version);
        run = new AtomicBoolean(false);
    }
    private CachingPublicKeyAuthenticator getPublicKeyAuthenticator(
            IKeyManager keyManager, IGitblit gitblit) {
        IStoredSettings settings = gitblit.getSettings();
        String clazz = settings.getString(Keys.git.sshPublicKeyAuthenticator,
                CachingPublicKeyAuthenticator.class.getName());
        if (StringUtils.isEmpty(clazz)) {
            clazz = CachingPublicKeyAuthenticator.class.getName();
        }
        try {
            Class<CachingPublicKeyAuthenticator> authClass =
                    (Class<CachingPublicKeyAuthenticator>) Class.forName(clazz);
            return authClass.getConstructor(
                    new Class[] { IKeyManager.class,
                            IAuthenticationManager.class }).newInstance(
                    keyManager, gitblit);
        } catch (Exception e) {
            log.error("failed to create ssh auth manager " + clazz, e);
        }
        return null;
    }
    public String formatUrl(String gituser, String servername, String repository) {
@@ -201,77 +169,6 @@
            } catch (InterruptedException e) {
                log.error("SSH Daemon stop interrupted", e);
            }
        }
    }
    @SuppressWarnings("unchecked")
    protected IKeyManager getKeyManager() {
        IKeyManager keyManager = null;
        IStoredSettings settings = gitblit.getSettings();
        String clazz = settings.getString(Keys.git.sshKeysManager, FileKeyManager.class.getName());
        if (StringUtils.isEmpty(clazz)) {
            clazz = FileKeyManager.class.getName();
        }
        try {
            Class<? extends IKeyManager> managerClass = (Class<? extends IKeyManager>) Class.forName(clazz);
            keyManager = injector.get(managerClass).start();
            if (keyManager.isReady()) {
                log.info("{} is ready.", keyManager);
            } else {
                log.warn("{} is disabled.", keyManager);
            }
        } catch (Exception e) {
            log.error("failed to create ssh key manager " + clazz, e);
            keyManager = injector.get(NullKeyManager.class).start();
        }
        return keyManager;
    }
    @SuppressWarnings("unchecked")
    protected IKeyManager getKeyAuthenticator() {
        IKeyManager keyManager = null;
        IStoredSettings settings = gitblit.getSettings();
        String clazz = settings.getString(Keys.git.sshKeysManager, FileKeyManager.class.getName());
        if (StringUtils.isEmpty(clazz)) {
            clazz = FileKeyManager.class.getName();
        }
        try {
            Class<? extends IKeyManager> managerClass = (Class<? extends IKeyManager>) Class.forName(clazz);
            keyManager = injector.get(managerClass).start();
            if (keyManager.isReady()) {
                log.info("{} is ready.", keyManager);
            } else {
                log.warn("{} is disabled.", keyManager);
            }
        } catch (Exception e) {
            log.error("failed to create ssh key manager " + clazz, e);
            keyManager = injector.get(NullKeyManager.class).start();
        }
        return keyManager;
    }
    /**
     * A nested Dagger graph is used for constructor dependency injection of
     * complex classes.
     *
     * @author James Moger
     *
     */
    @Module(
            library = true,
            injects = {
                    NullKeyManager.class,
                    FileKeyManager.class
            }
            )
    class SshModule {
        @Provides @Singleton NullKeyManager provideNullKeyManager() {
            return new NullKeyManager();
        }
        @Provides @Singleton FileKeyManager provideFileKeyManager() {
            return new FileKeyManager(SshDaemon.this.gitblit);
        }
    }
}
src/main/java/com/gitblit/transport/ssh/commands/DispatchCommand.java
@@ -32,8 +32,6 @@
import com.gitblit.models.UserModel;
import com.gitblit.transport.ssh.CommandMetaData;
import com.gitblit.transport.ssh.CachingPublicKeyAuthenticator;
import com.gitblit.transport.ssh.gitblit.BaseKeyCommand;
import com.gitblit.utils.StringUtils;
import com.gitblit.utils.cli.SubcommandHandler;
import com.google.common.base.Charsets;
@@ -252,16 +250,5 @@
        cmd.setOutputStream(out);
        cmd.setErrorStream(err);
        cmd.setExitCallback(exit);
        if (cmd instanceof BaseKeyCommand) {
            BaseKeyCommand k = (BaseKeyCommand) cmd;
            k.setAuthenticator(authenticator);
        }
    }
    private CachingPublicKeyAuthenticator authenticator;
    public void setAuthenticator(CachingPublicKeyAuthenticator authenticator) {
        this.authenticator = authenticator;
    }
}
src/main/java/com/gitblit/transport/ssh/gitblit/BaseKeyCommand.java
@@ -21,8 +21,7 @@
import java.io.UnsupportedEncodingException;
import java.util.List;
import com.gitblit.transport.ssh.IKeyManager;
import com.gitblit.transport.ssh.CachingPublicKeyAuthenticator;
import com.gitblit.transport.ssh.IPublicKeyManager;
import com.gitblit.transport.ssh.commands.SshCommand;
import com.google.common.base.Charsets;
@@ -53,12 +52,7 @@
        return sshKeys;
    }
    protected CachingPublicKeyAuthenticator authenticator;
    public void setAuthenticator(CachingPublicKeyAuthenticator authenticator) {
        this.authenticator = authenticator;
    }
    protected IKeyManager getKeyManager() {
        return authenticator.getKeyManager();
    protected IPublicKeyManager getKeyManager() {
        return ctx.getGitblit().getPublicKeyManager();
    }
}
src/main/java/com/gitblit/wicket/GitBlitWebApp.java
@@ -39,6 +39,7 @@
import com.gitblit.manager.IRuntimeManager;
import com.gitblit.manager.IUserManager;
import com.gitblit.tickets.ITicketService;
import com.gitblit.transport.ssh.IPublicKeyManager;
import com.gitblit.utils.StringUtils;
import com.gitblit.wicket.pages.ActivityPage;
import com.gitblit.wicket.pages.BlamePage;
@@ -95,6 +96,8 @@
    private final IAuthenticationManager authenticationManager;
    private final IPublicKeyManager publicKeyManager;
    private final IRepositoryManager repositoryManager;
    private final IProjectManager projectManager;
@@ -108,6 +111,7 @@
            INotificationManager notificationManager,
            IUserManager userManager,
            IAuthenticationManager authenticationManager,
            IPublicKeyManager publicKeyManager,
            IRepositoryManager repositoryManager,
            IProjectManager projectManager,
            IFederationManager federationManager,
@@ -119,6 +123,7 @@
        this.notificationManager = notificationManager;
        this.userManager = userManager;
        this.authenticationManager = authenticationManager;
        this.publicKeyManager = publicKeyManager;
        this.repositoryManager = repositoryManager;
        this.projectManager = projectManager;
        this.federationManager = federationManager;
@@ -280,6 +285,10 @@
        return authenticationManager;
    }
    public IPublicKeyManager keys() {
        return publicKeyManager;
    }
    public IRepositoryManager repositories() {
        return repositoryManager;
    }
src/test/config/test-gitblit.properties
@@ -8,7 +8,7 @@
git.enableGitServlet = true
git.daemonPort = 8300
git.sshPort = 29418
git.sshPublicKeyAuthenticator = com.gitblit.tests.BogusPublicKeyAuthenticator
git.sshKeysManager = com.gitblit.transport.ssh.MemoryKeyManager
groovy.scriptsFolder = src/main/distrib/data/groovy
groovy.preReceiveScripts = blockpush
groovy.postReceiveScripts = sendmail
src/test/java/com/gitblit/tests/BogusPublicKeyAuthenticator.java
File was deleted
src/test/java/com/gitblit/tests/GitBlitSuite.java
@@ -61,7 +61,7 @@
        MarkdownUtilsTest.class, JGitUtilsTest.class, SyndicationUtilsTest.class,
        DiffUtilsTest.class, MetricUtilsTest.class, X509UtilsTest.class,
        GitBlitTest.class, FederationTests.class, RpcTests.class, GitServletTest.class, GitDaemonTest.class,
        GroovyScriptTest.class, LuceneExecutorTest.class, RepositoryModelTest.class, SshDaemonTest.class,
        SshDaemonTest.class, GroovyScriptTest.class, LuceneExecutorTest.class, RepositoryModelTest.class,
        FanoutServiceTest.class, Issue0259Test.class, Issue0271Test.class, HtpasswdAuthenticationTest.class,
        ModelUtilsTest.class, JnaUtilsTest.class, LdapSyncServiceTest.class, FileTicketServiceTest.class,
        BranchTicketServiceTest.class, RedisTicketServiceTest.class, AuthenticationManagerTest.class })
@@ -78,20 +78,12 @@
    static int port = 8280;
    static int gitPort = 8300;
    static int shutdownPort = 8281;
    static int sshPort = 29418;
// Overriding of keys doesn't seem to work
//    static {
//        try {
//            sshPort = SshUtils.getFreePort();
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//    }
    static int sshPort = 39418;
    public static String url = "http://localhost:" + port;
    public static String gitServletUrl = "http://localhost:" + port + "/git";
    public static String gitDaemonUrl = "git://localhost:" + gitPort;
    public static String sshDaemonUrl = "ssh://admin@localhost:" + sshPort;
    public static String account = "admin";
    public static String password = "admin";
@@ -149,9 +141,7 @@
                        "" + shutdownPort, "--gitPort", "" + gitPort, "--repositoriesFolder",
                        "\"" + GitBlitSuite.REPOSITORIES.getAbsolutePath() + "\"", "--userService",
                        GitBlitSuite.USERSCONF.getAbsolutePath(), "--settings", GitBlitSuite.SETTINGS.getAbsolutePath(),
                        "--baseFolder", "data");
                // doesn't work
                //, "--sshPort", "" + sshPort);
                        "--baseFolder", "data", "--sshPort", "" + sshPort);
            }
        });
src/test/java/com/gitblit/tests/SshDaemonTest.java
@@ -26,11 +26,15 @@
import org.apache.sshd.ClientSession;
import org.apache.sshd.SshClient;
import org.apache.sshd.common.KeyPairProvider;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import com.gitblit.Constants;
import com.gitblit.transport.ssh.IPublicKeyManager;
import com.gitblit.transport.ssh.MemoryKeyManager;
public class SshDaemonTest extends GitblitUnitTest {
@@ -50,6 +54,27 @@
        }
    }
    protected MemoryKeyManager getKeyManager() {
        IPublicKeyManager mgr = gitblit().getPublicKeyManager();
        if (mgr instanceof MemoryKeyManager) {
            return (MemoryKeyManager) gitblit().getPublicKeyManager();
        } else {
            throw new RuntimeException("unexpected key manager type " + mgr.getClass().getName());
        }
    }
    @Before
    public void prepare() {
        MemoryKeyManager keyMgr = getKeyManager();
        keyMgr.addKey("admin", pair.getPublic());
    }
    @After
    public void tearDown() {
        MemoryKeyManager keyMgr = getKeyManager();
        keyMgr.removeAllKeys("admin");
    }
    @Test
    public void testPublicKeyAuthentication() throws Exception {
        SshClient client = SshClient.setUpDefaultClient();