From 31f477050f223b975bce4862a6aa415ee3045857 Mon Sep 17 00:00:00 2001 From: James Moger Date: Sat, 8 Mar 2014 19:10:20 -0500 Subject: Move Git daemon into different package --- src/main/java/com/gitblit/git/GitDaemon.java | 333 --------------------- src/main/java/com/gitblit/git/GitDaemonClient.java | 131 -------- .../java/com/gitblit/git/GitDaemonService.java | 166 ---------- .../com/gitblit/git/GitblitReceivePackFactory.java | 1 + .../com/gitblit/git/GitblitUploadPackFactory.java | 4 +- .../java/com/gitblit/git/RepositoryResolver.java | 1 + 6 files changed, 5 insertions(+), 631 deletions(-) delete mode 100644 src/main/java/com/gitblit/git/GitDaemon.java delete mode 100644 src/main/java/com/gitblit/git/GitDaemonClient.java delete mode 100644 src/main/java/com/gitblit/git/GitDaemonService.java (limited to 'src/main/java/com/gitblit/git') diff --git a/src/main/java/com/gitblit/git/GitDaemon.java b/src/main/java/com/gitblit/git/GitDaemon.java deleted file mode 100644 index d026b5ed..00000000 --- a/src/main/java/com/gitblit/git/GitDaemon.java +++ /dev/null @@ -1,333 +0,0 @@ -/* - * Copyright (C) 2013 gitblit.com - * Copyright (C) 2008-2009, Google Inc. - * and other copyright owners as documented in the project's IP log. - * - * This program and the accompanying materials are made available - * under the terms of the Eclipse Distribution License v1.0 which - * accompanies this distribution, is reproduced below, and is - * available at http://www.eclipse.org/org/documents/edl-v10.php - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - * - Neither the name of the Eclipse Foundation, Inc. nor the - * names of its contributors may be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.gitblit.git; - -import java.io.IOException; -import java.io.InputStream; -import java.io.InterruptedIOException; -import java.io.OutputStream; -import java.net.InetSocketAddress; -import java.net.ServerSocket; -import java.net.Socket; -import java.net.SocketAddress; -import java.text.MessageFormat; -import java.util.concurrent.atomic.AtomicBoolean; - -import org.eclipse.jgit.errors.RepositoryNotFoundException; -import org.eclipse.jgit.internal.JGitText; -import org.eclipse.jgit.lib.Repository; -import org.eclipse.jgit.transport.ReceivePack; -import org.eclipse.jgit.transport.ServiceMayNotContinueException; -import org.eclipse.jgit.transport.UploadPack; -import org.eclipse.jgit.transport.resolver.ReceivePackFactory; -import org.eclipse.jgit.transport.resolver.ServiceNotAuthorizedException; -import org.eclipse.jgit.transport.resolver.ServiceNotEnabledException; -import org.eclipse.jgit.transport.resolver.UploadPackFactory; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.gitblit.IStoredSettings; -import com.gitblit.Keys; -import com.gitblit.manager.IGitblit; -import com.gitblit.utils.StringUtils; - -/** - * Gitblit's Git Daemon ignores any and all per-repository daemon settings and - * integrates into Gitblit's security model. - * - * @author James Moger - * - */ -public class GitDaemon { - - private final Logger logger = LoggerFactory.getLogger(GitDaemon.class); - - /** 9418: IANA assigned port number for Git. */ - public static final int DEFAULT_PORT = 9418; - - private static final int BACKLOG = 5; - - private InetSocketAddress myAddress; - - private final GitDaemonService[] services; - - private final ThreadGroup processors; - - private AtomicBoolean run; - - private ServerSocket acceptSocket; - - private Thread acceptThread; - - private int timeout; - - private RepositoryResolver repositoryResolver; - - private UploadPackFactory uploadPackFactory; - - private ReceivePackFactory receivePackFactory; - - public GitDaemon(IGitblit gitblit) { - - IStoredSettings settings = gitblit.getSettings(); - int port = settings.getInteger(Keys.git.daemonPort, 0); - String bindInterface = settings.getString(Keys.git.daemonBindInterface, "localhost"); - - if (StringUtils.isEmpty(bindInterface)) { - myAddress = new InetSocketAddress(port); - } else { - myAddress = new InetSocketAddress(bindInterface, port); - } - - repositoryResolver = new RepositoryResolver(gitblit); - uploadPackFactory = new GitblitUploadPackFactory(gitblit); - receivePackFactory = new GitblitReceivePackFactory(gitblit); - - run = new AtomicBoolean(false); - processors = new ThreadGroup("Git-Daemon"); - services = new GitDaemonService[] { new GitDaemonService("upload-pack", "uploadpack") { - { - setEnabled(true); - setOverridable(false); - } - - @Override - protected void execute(final GitDaemonClient dc, final Repository db) - throws IOException, ServiceNotEnabledException, - ServiceNotAuthorizedException { - UploadPack up = uploadPackFactory.create(dc, db); - InputStream in = dc.getInputStream(); - OutputStream out = dc.getOutputStream(); - up.upload(in, out, null); - } - }, new GitDaemonService("receive-pack", "receivepack") { - { - setEnabled(true); - setOverridable(false); - } - - @Override - protected void execute(final GitDaemonClient dc, final Repository db) - throws IOException, ServiceNotEnabledException, - ServiceNotAuthorizedException { - ReceivePack rp = receivePackFactory.create(dc, db); - InputStream in = dc.getInputStream(); - OutputStream out = dc.getOutputStream(); - rp.receive(in, out, null); - } - } }; - } - - public int getPort() { - return myAddress.getPort(); - } - - public String formatUrl(String servername, String repository) { - if (getPort() == 9418) { - // standard port - return MessageFormat.format("git://{0}/{1}", servername, repository); - } else { - // non-standard port - return MessageFormat.format("git://{0}:{1,number,0}/{2}", servername, getPort(), repository); - } - } - - /** @return timeout (in seconds) before aborting an IO operation. */ - public int getTimeout() { - return timeout; - } - - /** - * Set the timeout before willing to abort an IO call. - * - * @param seconds - * number of seconds to wait (with no data transfer occurring) - * before aborting an IO read or write operation with the - * connected client. - */ - public void setTimeout(final int seconds) { - timeout = seconds; - } - - /** - * Start this daemon on a background thread. - * - * @throws IOException - * the server socket could not be opened. - * @throws IllegalStateException - * the daemon is already running. - */ - public synchronized void start() throws IOException { - if (acceptThread != null) - throw new IllegalStateException(JGitText.get().daemonAlreadyRunning); - - final ServerSocket listenSock = new ServerSocket(myAddress != null ? myAddress.getPort() - : 0, BACKLOG, myAddress != null ? myAddress.getAddress() : null); - myAddress = (InetSocketAddress) listenSock.getLocalSocketAddress(); - - run.set(true); - acceptSocket = listenSock; - acceptThread = new Thread(processors, "Git-Daemon-Accept") { - @Override - public void run() { - while (isRunning()) { - try { - startClient(listenSock.accept()); - } catch (InterruptedIOException e) { - // Test again to see if we should keep accepting. - } catch (IOException e) { - break; - } - } - - try { - listenSock.close(); - } catch (IOException err) { - // - } finally { - acceptSocket = null; - } - - } - }; - acceptThread.start(); - - logger.info(MessageFormat.format("Git Daemon is listening on {0}:{1,number,0}", myAddress.getAddress().getHostAddress(), myAddress.getPort())); - } - - /** @return true if this daemon is receiving connections. */ - public boolean isRunning() { - return run.get(); - } - - /** Stop this daemon. */ - public synchronized void stop() { - if (isRunning() && acceptThread != null) { - run.set(false); - logger.info("Git Daemon stopping..."); - try { - // close the accept socket - // this throws a SocketException in the accept thread - acceptSocket.close(); - } catch (IOException e1) { - } - try { - // join the accept thread - acceptThread.join(); - logger.info("Git Daemon stopped."); - } catch (InterruptedException e) { - logger.error("Accept thread join interrupted", e); - } finally { - acceptThread = null; - } - } - } - - private void startClient(final Socket s) { - final GitDaemonClient dc = new GitDaemonClient(this); - - final SocketAddress peer = s.getRemoteSocketAddress(); - if (peer instanceof InetSocketAddress) - dc.setRemoteAddress(((InetSocketAddress) peer).getAddress()); - - new Thread(processors, "Git-Daemon-Client " + peer.toString()) { - @Override - public void run() { - try { - dc.execute(s); - } catch (ServiceNotEnabledException e) { - // Ignored. Client cannot use this repository. - } catch (ServiceNotAuthorizedException e) { - // Ignored. Client cannot use this repository. - } catch (IOException e) { - // Ignore unexpected IO exceptions from clients - } finally { - try { - s.getInputStream().close(); - } catch (IOException e) { - // Ignore close exceptions - } - try { - s.getOutputStream().close(); - } catch (IOException e) { - // Ignore close exceptions - } - } - } - }.start(); - } - - synchronized GitDaemonService matchService(final String cmd) { - for (final GitDaemonService d : services) { - if (d.handles(cmd)) - return d; - } - return null; - } - - Repository openRepository(GitDaemonClient client, String name) - throws ServiceMayNotContinueException { - // Assume any attempt to use \ was by a Windows client - // and correct to the more typical / used in Git URIs. - // - name = name.replace('\\', '/'); - - // git://thishost/path should always be name="/path" here - // - if (!name.startsWith("/")) //$NON-NLS-1$ - return null; - - try { - return repositoryResolver.open(client, name.substring(1)); - } catch (RepositoryNotFoundException e) { - // null signals it "wasn't found", which is all that is suitable - // for the remote client to know. - return null; - } catch (ServiceNotEnabledException e) { - // null signals it "wasn't found", which is all that is suitable - // for the remote client to know. - return null; - } - } -} diff --git a/src/main/java/com/gitblit/git/GitDaemonClient.java b/src/main/java/com/gitblit/git/GitDaemonClient.java deleted file mode 100644 index 8d8cac6d..00000000 --- a/src/main/java/com/gitblit/git/GitDaemonClient.java +++ /dev/null @@ -1,131 +0,0 @@ -package com.gitblit.git; - -/* - * Copyright (C) 2008-2009, Google Inc. - * and other copyright owners as documented in the project's IP log. - * - * This program and the accompanying materials are made available - * under the terms of the Eclipse Distribution License v1.0 which - * accompanies this distribution, is reproduced below, and is - * available at http://www.eclipse.org/org/documents/edl-v10.php - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - * - Neither the name of the Eclipse Foundation, Inc. nor the - * names of its contributors may be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -import java.io.BufferedInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.InetAddress; -import java.net.Socket; - -import org.eclipse.jgit.transport.Daemon; -import org.eclipse.jgit.transport.PacketLineIn; -import org.eclipse.jgit.transport.resolver.ServiceNotAuthorizedException; -import org.eclipse.jgit.transport.resolver.ServiceNotEnabledException; -import org.eclipse.jgit.util.io.SafeBufferedOutputStream; - -/** Active network client of {@link Daemon}. */ -public class GitDaemonClient { - private final GitDaemon daemon; - - private InetAddress peer; - - private InputStream rawIn; - - private OutputStream rawOut; - - private String repositoryName; - - GitDaemonClient(final GitDaemon d) { - daemon = d; - } - - void setRemoteAddress(final InetAddress ia) { - peer = ia; - } - - /** @return the daemon which spawned this client. */ - public GitDaemon getDaemon() { - return daemon; - } - - /** @return Internet address of the remote client. */ - public InetAddress getRemoteAddress() { - return peer; - } - - /** @return input stream to read from the connected client. */ - public InputStream getInputStream() { - return rawIn; - } - - /** @return output stream to send data to the connected client. */ - public OutputStream getOutputStream() { - return rawOut; - } - - public void setRepositoryName(String repositoryName) { - this.repositoryName = repositoryName; - } - - /** @return the name of the requested repository. */ - public String getRepositoryName() { - return repositoryName; - } - - void execute(final Socket sock) throws IOException, - ServiceNotEnabledException, ServiceNotAuthorizedException { - rawIn = new BufferedInputStream(sock.getInputStream()); - rawOut = new SafeBufferedOutputStream(sock.getOutputStream()); - - if (0 < daemon.getTimeout()) - sock.setSoTimeout(daemon.getTimeout() * 1000); - String cmd = new PacketLineIn(rawIn).readStringRaw(); - final int nul = cmd.indexOf('\0'); - if (nul >= 0) { - // Newer clients hide a "host" header behind this byte. - // Currently we don't use it for anything, so we ignore - // this portion of the command. - // - cmd = cmd.substring(0, nul); - } - - final GitDaemonService srv = getDaemon().matchService(cmd); - if (srv == null) - return; - sock.setSoTimeout(0); - srv.execute(this, cmd); - } -} \ No newline at end of file diff --git a/src/main/java/com/gitblit/git/GitDaemonService.java b/src/main/java/com/gitblit/git/GitDaemonService.java deleted file mode 100644 index 8dee7d0b..00000000 --- a/src/main/java/com/gitblit/git/GitDaemonService.java +++ /dev/null @@ -1,166 +0,0 @@ -package com.gitblit.git; - -/* - * Copyright (C) 2008-2009, Google Inc. - * Copyright (C) 2009, Robin Rosenberg - * and other copyright owners as documented in the project's IP log. - * - * This program and the accompanying materials are made available - * under the terms of the Eclipse Distribution License v1.0 which - * accompanies this distribution, is reproduced below, and is - * available at http://www.eclipse.org/org/documents/edl-v10.php - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - * - Neither the name of the Eclipse Foundation, Inc. nor the - * names of its contributors may be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -import java.io.IOException; - -import org.eclipse.jgit.lib.Config; -import org.eclipse.jgit.lib.Config.SectionParser; -import org.eclipse.jgit.lib.Repository; -import org.eclipse.jgit.transport.Daemon; -import org.eclipse.jgit.transport.PacketLineOut; -import org.eclipse.jgit.transport.ServiceMayNotContinueException; -import org.eclipse.jgit.transport.resolver.ServiceNotAuthorizedException; -import org.eclipse.jgit.transport.resolver.ServiceNotEnabledException; - -/** A service exposed by {@link Daemon} over anonymous git://. */ -public abstract class GitDaemonService { - private final String command; - - private final SectionParser configKey; - - private boolean enabled; - - private boolean overridable; - - GitDaemonService(final String cmdName, final String cfgName) { - command = cmdName.startsWith("git-") ? cmdName : "git-" + cmdName; //$NON-NLS-1$ //$NON-NLS-2$ - configKey = new SectionParser() { - @Override - public ServiceConfig parse(final Config cfg) { - return new ServiceConfig(GitDaemonService.this, cfg, cfgName); - } - }; - overridable = true; - } - - private static class ServiceConfig { - final boolean enabled; - - ServiceConfig(final GitDaemonService service, final Config cfg, - final String name) { - enabled = cfg.getBoolean("daemon", name, service.isEnabled()); //$NON-NLS-1$ - } - } - - /** @return is this service enabled for invocation? */ - public boolean isEnabled() { - return enabled; - } - - /** - * @param on - * true to allow this service to be used; false to deny it. - */ - public void setEnabled(final boolean on) { - enabled = on; - } - - /** @return can this service be configured in the repository config file? */ - public boolean isOverridable() { - return overridable; - } - - /** - * @param on - * true to permit repositories to override this service's enabled - * state with the daemon.servicename config setting. - */ - public void setOverridable(final boolean on) { - overridable = on; - } - - /** @return name of the command requested by clients. */ - public String getCommandName() { - return command; - } - - /** - * Determine if this service can handle the requested command. - * - * @param commandLine - * input line from the client. - * @return true if this command can accept the given command line. - */ - public boolean handles(final String commandLine) { - return command.length() + 1 < commandLine.length() - && commandLine.charAt(command.length()) == ' ' - && commandLine.startsWith(command); - } - - void execute(final GitDaemonClient client, final String commandLine) - throws IOException, ServiceNotEnabledException, - ServiceNotAuthorizedException { - final String name = commandLine.substring(command.length() + 1); - Repository db; - try { - db = client.getDaemon().openRepository(client, name); - } catch (ServiceMayNotContinueException e) { - // An error when opening the repo means the client is expecting a ref - // advertisement, so use that style of error. - PacketLineOut pktOut = new PacketLineOut(client.getOutputStream()); - pktOut.writeString("ERR " + e.getMessage() + "\n"); //$NON-NLS-1$ //$NON-NLS-2$ - db = null; - } - if (db == null) - return; - try { - if (isEnabledFor(db)) - execute(client, db); - } finally { - db.close(); - } - } - - private boolean isEnabledFor(final Repository db) { - if (isOverridable()) - return db.getConfig().get(configKey).enabled; - return isEnabled(); - } - - abstract void execute(GitDaemonClient client, Repository db) - throws IOException, ServiceNotEnabledException, - ServiceNotAuthorizedException; -} diff --git a/src/main/java/com/gitblit/git/GitblitReceivePackFactory.java b/src/main/java/com/gitblit/git/GitblitReceivePackFactory.java index 9911258c..af5a8381 100644 --- a/src/main/java/com/gitblit/git/GitblitReceivePackFactory.java +++ b/src/main/java/com/gitblit/git/GitblitReceivePackFactory.java @@ -31,6 +31,7 @@ import com.gitblit.Keys; import com.gitblit.manager.IGitblit; import com.gitblit.models.RepositoryModel; import com.gitblit.models.UserModel; +import com.gitblit.transport.git.GitDaemonClient; import com.gitblit.transport.ssh.SshSession; import com.gitblit.utils.HttpUtils; import com.gitblit.utils.StringUtils; diff --git a/src/main/java/com/gitblit/git/GitblitUploadPackFactory.java b/src/main/java/com/gitblit/git/GitblitUploadPackFactory.java index d4e3ca15..39ad0724 100644 --- a/src/main/java/com/gitblit/git/GitblitUploadPackFactory.java +++ b/src/main/java/com/gitblit/git/GitblitUploadPackFactory.java @@ -25,6 +25,7 @@ import org.eclipse.jgit.transport.resolver.UploadPackFactory; import com.gitblit.manager.IAuthenticationManager; import com.gitblit.models.UserModel; +import com.gitblit.transport.git.GitDaemonClient; /** * The upload pack factory creates an upload pack which controls what refs are @@ -51,7 +52,8 @@ public class GitblitUploadPackFactory implements UploadPackFactory { if (req instanceof HttpServletRequest) { // http/https request may or may not be authenticated - user = authenticationManager.authenticate((HttpServletRequest) req); + HttpServletRequest client = (HttpServletRequest) req; + user = authenticationManager.authenticate(client); if (user == null) { user = UserModel.ANONYMOUS; } diff --git a/src/main/java/com/gitblit/git/RepositoryResolver.java b/src/main/java/com/gitblit/git/RepositoryResolver.java index c859f6f6..08048195 100644 --- a/src/main/java/com/gitblit/git/RepositoryResolver.java +++ b/src/main/java/com/gitblit/git/RepositoryResolver.java @@ -30,6 +30,7 @@ import org.slf4j.LoggerFactory; import com.gitblit.manager.IGitblit; import com.gitblit.models.RepositoryModel; import com.gitblit.models.UserModel; +import com.gitblit.transport.git.GitDaemonClient; import com.gitblit.transport.ssh.SshSession; /** -- cgit v1.2.3