From 245836904ba5cecdc31773cf7c9616396c8ad8c0 Mon Sep 17 00:00:00 2001
From: James Moger <james.moger@gitblit.com>
Date: Thu, 10 Apr 2014 18:58:09 -0400
Subject: [PATCH] Elevate the public key manager to a top-level manager

---
 src/main/java/com/gitblit/servlet/GitblitContext.java                      |    4 
 src/main/java/com/gitblit/transport/ssh/MemoryKeyManager.java              |   98 ++++++++++++
 src/main/java/com/gitblit/transport/ssh/gitblit/BaseKeyCommand.java        |   12 -
 src/test/java/com/gitblit/tests/SshDaemonTest.java                         |   25 +++
 src/main/java/com/gitblit/transport/ssh/IPublicKeyManager.java             |   10 
 src/main/java/com/gitblit/wicket/GitBlitWebApp.java                        |    9 +
 src/main/distrib/data/gitblit.properties                                   |    5 
 src/main/java/com/gitblit/GitBlit.java                                     |    5 
 src/main/java/com/gitblit/transport/ssh/CachingPublicKeyAuthenticator.java |   15 -
 src/main/java/com/gitblit/transport/ssh/NullKeyManager.java                |    5 
 /dev/null                                                                  |   39 ----
 src/test/java/com/gitblit/tests/GitBlitSuite.java                          |   18 -
 src/main/java/com/gitblit/transport/ssh/FileKeyManager.java                |    5 
 src/main/java/com/gitblit/transport/ssh/SshDaemon.java                     |  107 -------------
 src/main/java/com/gitblit/DaggerModule.java                                |   37 ++++
 src/main/java/com/gitblit/manager/IGitblit.java                            |    8 +
 src/main/java/com/gitblit/FederationClient.java                            |    2 
 src/main/java/com/gitblit/manager/GitblitManager.java                      |   10 +
 src/main/java/com/gitblit/transport/ssh/commands/DispatchCommand.java      |   13 -
 src/main/java/com/gitblit/transport/ssh/SshCommandFactory.java             |    8 
 src/test/config/test-gitblit.properties                                    |    2 
 21 files changed, 225 insertions(+), 212 deletions(-)

diff --git a/src/main/distrib/data/gitblit.properties b/src/main/distrib/data/gitblit.properties
index 52bb252..64a52f5 100644
--- a/src/main/distrib/data/gitblit.properties
+++ b/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://.
diff --git a/src/main/java/com/gitblit/DaggerModule.java b/src/main/java/com/gitblit/DaggerModule.java
index 5ae8b25..b109f1d 100644
--- a/src/main/java/com/gitblit/DaggerModule.java
+++ b/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,
diff --git a/src/main/java/com/gitblit/FederationClient.java b/src/main/java/com/gitblit/FederationClient.java
index 792a638..d20025f 100644
--- a/src/main/java/com/gitblit/FederationClient.java
+++ b/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
diff --git a/src/main/java/com/gitblit/GitBlit.java b/src/main/java/com/gitblit/GitBlit.java
index 817d18c..b223d03 100644
--- a/src/main/java/com/gitblit/GitBlit.java
+++ b/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 {
 
diff --git a/src/main/java/com/gitblit/manager/GitblitManager.java b/src/main/java/com/gitblit/manager/GitblitManager.java
index 97e8efc..8856715 100644
--- a/src/main/java/com/gitblit/manager/GitblitManager.java
+++ b/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
 	 *
diff --git a/src/main/java/com/gitblit/manager/IGitblit.java b/src/main/java/com/gitblit/manager/IGitblit.java
index 50210e9..f4221cf 100644
--- a/src/main/java/com/gitblit/manager/IGitblit.java
+++ b/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();
+
 }
\ No newline at end of file
diff --git a/src/main/java/com/gitblit/servlet/GitblitContext.java b/src/main/java/com/gitblit/servlet/GitblitContext.java
index d4ec967..cf8bba0 100644
--- a/src/main/java/com/gitblit/servlet/GitblitContext.java
+++ b/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);
diff --git a/src/main/java/com/gitblit/transport/ssh/CachingPublicKeyAuthenticator.java b/src/main/java/com/gitblit/transport/ssh/CachingPublicKeyAuthenticator.java
index 7d6066c..0120fa6 100644
--- a/src/main/java/com/gitblit/transport/ssh/CachingPublicKeyAuthenticator.java
+++ b/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);
 	}
diff --git a/src/main/java/com/gitblit/transport/ssh/FileKeyManager.java b/src/main/java/com/gitblit/transport/ssh/FileKeyManager.java
index ae0bc9c..defb4a3 100644
--- a/src/main/java/com/gitblit/transport/ssh/FileKeyManager.java
+++ b/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;
 	}
 
diff --git a/src/main/java/com/gitblit/transport/ssh/IKeyManager.java b/src/main/java/com/gitblit/transport/ssh/IPublicKeyManager.java
similarity index 89%
rename from src/main/java/com/gitblit/transport/ssh/IKeyManager.java
rename to src/main/java/com/gitblit/transport/ssh/IPublicKeyManager.java
index 12fce3d..5857a59 100644
--- a/src/main/java/com/gitblit/transport/ssh/IKeyManager.java
+++ b/src/main/java/com/gitblit/transport/ssh/IPublicKeyManager.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 {
diff --git a/src/main/java/com/gitblit/transport/ssh/MemoryKeyManager.java b/src/main/java/com/gitblit/transport/ssh/MemoryKeyManager.java
new file mode 100644
index 0000000..26bd021
--- /dev/null
+++ b/src/main/java/com/gitblit/transport/ssh/MemoryKeyManager.java
@@ -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);
+	}
+}
diff --git a/src/main/java/com/gitblit/transport/ssh/NullKeyManager.java b/src/main/java/com/gitblit/transport/ssh/NullKeyManager.java
index c76728d..25860d6 100644
--- a/src/main/java/com/gitblit/transport/ssh/NullKeyManager.java
+++ b/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;
 	}
 
diff --git a/src/main/java/com/gitblit/transport/ssh/SshCommandFactory.java b/src/main/java/com/gitblit/transport/ssh/SshCommandFactory.java
index de7aad1..2b2093e 100644
--- a/src/main/java/com/gitblit/transport/ssh/SshCommandFactory.java
+++ b/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;
 	}
diff --git a/src/main/java/com/gitblit/transport/ssh/SshDaemon.java b/src/main/java/com/gitblit/transport/ssh/SshDaemon.java
index b6c5d68..da9a372 100644
--- a/src/main/java/com/gitblit/transport/ssh/SshDaemon.java
+++ b/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);
 		}
 	}
 }
diff --git a/src/main/java/com/gitblit/transport/ssh/commands/DispatchCommand.java b/src/main/java/com/gitblit/transport/ssh/commands/DispatchCommand.java
index 38f1a48..dd581f4 100644
--- a/src/main/java/com/gitblit/transport/ssh/commands/DispatchCommand.java
+++ b/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;
 	}
 }
diff --git a/src/main/java/com/gitblit/transport/ssh/gitblit/BaseKeyCommand.java b/src/main/java/com/gitblit/transport/ssh/gitblit/BaseKeyCommand.java
index 0909957..1b7bac1 100644
--- a/src/main/java/com/gitblit/transport/ssh/gitblit/BaseKeyCommand.java
+++ b/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();
 	}
 }
diff --git a/src/main/java/com/gitblit/wicket/GitBlitWebApp.java b/src/main/java/com/gitblit/wicket/GitBlitWebApp.java
index 445335f..6e8aa05 100644
--- a/src/main/java/com/gitblit/wicket/GitBlitWebApp.java
+++ b/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;
 	}
diff --git a/src/test/config/test-gitblit.properties b/src/test/config/test-gitblit.properties
index 7d8e9a7..1a52eaf 100644
--- a/src/test/config/test-gitblit.properties
+++ b/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
diff --git a/src/test/java/com/gitblit/tests/BogusPublicKeyAuthenticator.java b/src/test/java/com/gitblit/tests/BogusPublicKeyAuthenticator.java
deleted file mode 100644
index 80be1a0..0000000
--- a/src/test/java/com/gitblit/tests/BogusPublicKeyAuthenticator.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * 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.tests;
-
-import java.security.PublicKey;
-
-import org.apache.sshd.server.session.ServerSession;
-
-import com.gitblit.manager.IAuthenticationManager;
-import com.gitblit.transport.ssh.CachingPublicKeyAuthenticator;
-import com.gitblit.transport.ssh.IKeyManager;
-
-public class BogusPublicKeyAuthenticator extends CachingPublicKeyAuthenticator {
-
-	public BogusPublicKeyAuthenticator(IKeyManager keyManager,
-			IAuthenticationManager authManager) {
-		super(keyManager, authManager);
-	}
-
-	@Override
-	protected boolean doAuthenticate(String username, PublicKey suppliedKey,
-			ServerSession session) {
-		// TODO(davido): put authenticated user in session
-		return true;
-	}
-}
diff --git a/src/test/java/com/gitblit/tests/GitBlitSuite.java b/src/test/java/com/gitblit/tests/GitBlitSuite.java
index 17d609e..b8d3b18 100644
--- a/src/test/java/com/gitblit/tests/GitBlitSuite.java
+++ b/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);
 			}
 		});
 
diff --git a/src/test/java/com/gitblit/tests/SshDaemonTest.java b/src/test/java/com/gitblit/tests/SshDaemonTest.java
index 5294f69..45d31c2 100644
--- a/src/test/java/com/gitblit/tests/SshDaemonTest.java
+++ b/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();

--
Gitblit v1.9.1