From 7b6c1bdaba9877397ffdaf0c8641196cfb060c39 Mon Sep 17 00:00:00 2001
From: Vitaliy Filippov <vitalif@yourcmc.ru>
Date: Thu, 01 Oct 2015 06:08:53 -0400
Subject: [PATCH] Allow to strip domain from kerberos usernames

---
 src/main/java/com/gitblit/transport/ssh/SshDaemon.java |   92 ++++++++++++++++++++++++++++++++++++++++------
 1 files changed, 80 insertions(+), 12 deletions(-)

diff --git a/src/main/java/com/gitblit/transport/ssh/SshDaemon.java b/src/main/java/com/gitblit/transport/ssh/SshDaemon.java
index 4d64cfb..65d1558 100644
--- a/src/main/java/com/gitblit/transport/ssh/SshDaemon.java
+++ b/src/main/java/com/gitblit/transport/ssh/SshDaemon.java
@@ -23,14 +23,24 @@
 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.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.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;
@@ -41,9 +51,9 @@
 import com.gitblit.Keys;
 import com.gitblit.manager.IGitblit;
 import com.gitblit.transport.ssh.commands.SshCommandFactory;
-import com.gitblit.utils.IdGenerator;
 import com.gitblit.utils.JnaUtils;
 import com.gitblit.utils.StringUtils;
+import com.gitblit.utils.WorkQueue;
 import com.google.common.io.Files;
 
 /**
@@ -76,14 +86,18 @@
 	 * Construct the Gitblit SSH daemon.
 	 *
 	 * @param gitblit
+	 * @param workQueue
 	 */
-	public SshDaemon(IGitblit gitblit, IdGenerator idGenerator) {
+	public SshDaemon(IGitblit gitblit, WorkQueue workQueue) {
 		this.gitblit = gitblit;
 
 		IStoredSettings settings = gitblit.getSettings();
 
 		// Ensure that Bouncy Castle is our JCE provider
 		SecurityUtils.setRegisterBouncyCastle(true);
+		if (SecurityUtils.isBouncyCastleRegistered()) {
+			log.debug("BouncyCastle is registered as a JCE provider");
+		}
 
 		// Generate host RSA and DSA keypairs and create the host keypair provider
 		File rsaKeyStore = new File(gitblit.getBaseFolder(), "ssh-rsa-hostkey.pem");
@@ -94,8 +108,8 @@
 		hostKeyPairProvider.setFiles(new String [] { rsaKeyStore.getPath(), dsaKeyStore.getPath(), dsaKeyStore.getPath() });
 
 		// Client public key authenticator
-		CachingPublicKeyAuthenticator keyAuthenticator =
-				new CachingPublicKeyAuthenticator(gitblit.getPublicKeyManager(), gitblit);
+		SshKeyAuthenticator keyAuthenticator =
+				new SshKeyAuthenticator(gitblit.getPublicKeyManager(), gitblit);
 
 		// Configure the preferred SSHD backend
 		String sshBackendStr = settings.getString(Keys.git.sshBackend,
@@ -116,17 +130,63 @@
 			addr = new InetSocketAddress(bindInterface, port);
 		}
 
+		//Will do GSS ?
+		GSSAuthenticator gssAuthenticator = null;
+		if(settings.getBoolean(Keys.git.sshWithKrb5, false)) {
+			gssAuthenticator = new SshKrbAuthenticator(gitblit, settings.getBoolean(Keys.git.sshKrb5StripDomain, false));
+			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());
 		sshd.setHost(addr.getHostName());
 		sshd.setKeyPairProvider(hostKeyPairProvider);
-		sshd.setPublickeyAuthenticator(keyAuthenticator);
+		sshd.setPublickeyAuthenticator(new CachingPublicKeyAuthenticator(keyAuthenticator));
 		sshd.setPasswordAuthenticator(new UsernamePasswordAuthenticator(gitblit));
+		if(gssAuthenticator != null) {
+			sshd.setGSSAuthenticator(gssAuthenticator);
+		}
+		sshd.setUserAuthFactories(userAuthFactories);
 		sshd.setSessionFactory(new SshServerSessionFactory());
 		sshd.setFileSystemFactory(new DisabledFilesystemFactory());
 		sshd.setTcpipForwardingFilter(new NonForwardingFilter());
-		sshd.setCommandFactory(new SshCommandFactory(gitblit, idGenerator));
+		sshd.setCommandFactory(new SshCommandFactory(gitblit, workQueue));
 		sshd.setShellFactory(new WelcomeShell(settings));
 
 		// Set the server id.  This can be queried with:
@@ -139,14 +199,22 @@
 	}
 
 	public String formatUrl(String gituser, String servername, String repository) {
-		if (sshd.getPort() == DEFAULT_PORT) {
+		IStoredSettings settings = gitblit.getSettings();
+
+		int port = sshd.getPort();
+		int displayPort = settings.getInteger(Keys.git.sshAdvertisedPort, port);
+		String displayServername = settings.getString(Keys.git.sshAdvertisedHost, "");
+		if(displayServername.isEmpty()) {
+			displayServername = servername;
+		}
+		if (displayPort == DEFAULT_PORT) {
 			// standard port
-			return MessageFormat.format("{0}@{1}/{2}", gituser, servername,
+			return MessageFormat.format("ssh://{0}@{1}/{2}", gituser, displayServername,
 					repository);
 		} else {
 			// non-standard port
 			return MessageFormat.format("ssh://{0}@{1}:{2,number,0}/{3}",
-					gituser, servername, sshd.getPort(), repository);
+					gituser, displayServername, displayPort, repository);
 		}
 	}
 
@@ -188,7 +256,7 @@
 			try {
 				((SshCommandFactory) sshd.getCommandFactory()).stop();
 				sshd.stop();
-			} catch (InterruptedException e) {
+			} catch (IOException e) {
 				log.error("SSH Daemon stop interrupted", e);
 			}
 		}

--
Gitblit v1.9.1