Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ mvn.out*
.settings/
.repository/
.settings.xml
.idea/
41 changes: 21 additions & 20 deletions pom.xml
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>plugin</artifactId>
<version>4.86</version>
<relativePath/>
Comment thread
mtughan marked this conversation as resolved.
<version>5.6</version>
<relativePath />
</parent>

<artifactId>git-server</artifactId>
Expand All @@ -15,21 +16,6 @@
<name>Jenkins Git server Plugin</name>
<url>https://github.com/jenkinsci/${project.artifactId}-plugin</url>

<properties>
<changelist>999999-SNAPSHOT</changelist>
<!-- https://www.jenkins.io/doc/developer/plugin-development/choosing-jenkins-baseline/ -->
<jenkins.baseline>2.440</jenkins.baseline>
<jenkins.version>${jenkins.baseline}.3</jenkins.version>
<gitHubRepo>jenkinsci/${project.artifactId}-plugin</gitHubRepo>
</properties>

<scm>
<connection>scm:git:https://github.com/${gitHubRepo}.git</connection>
<developerConnection>scm:git:git@github.com:${gitHubRepo}.git</developerConnection>
<url>https://github.com/${gitHubRepo}</url>
<tag>${scmTag}</tag>
</scm>

<licenses>
<license>
<name>The MIT license</name>
Expand All @@ -38,14 +24,29 @@
</license>
</licenses>

<scm>
<connection>scm:git:https://github.com/${gitHubRepo}.git</connection>
<developerConnection>scm:git:git@github.com:${gitHubRepo}.git</developerConnection>
<tag>${scmTag}</tag>
<url>https://github.com/${gitHubRepo}</url>
</scm>

<properties>
<changelist>999999-SNAPSHOT</changelist>
<!-- https://www.jenkins.io/doc/developer/plugin-development/choosing-jenkins-baseline/ -->
<jenkins.baseline>2.479</jenkins.baseline>
<jenkins.version>${jenkins.baseline}.1</jenkins.version>
<gitHubRepo>jenkinsci/${project.artifactId}-plugin</gitHubRepo>
</properties>

<dependencyManagement>
<dependencies>
<dependency>
<groupId>io.jenkins.tools.bom</groupId>
<artifactId>bom-${jenkins.baseline}.x</artifactId>
<version>3234.v5ca_5154341ef</version>
<scope>import</scope>
<version>4023.va_eeb_b_4e45f07</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
Expand All @@ -67,7 +68,7 @@
<dependency>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit.ssh.apache</artifactId>
<version>6.9.0.202403050737-r</version>
<version>7.0.0.202409031743-r</version>
<scope>test</scope>
</dependency>
<dependency>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,31 @@

import hudson.Extension;
import hudson.security.csrf.CrumbExclusion;

import javax.servlet.FilterChain;
import javax.servlet.ReadListener;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ReadListener;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletInputStream;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletRequestWrapper;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Locale;
import java.util.Map;
import java.util.Vector;

/**
* CSRF exclusion for git-upload-pack.
*
*
* <p>
* We do some basic checks to significantly limit the scope of exclusion, but
* because of the dynamic nature of the URL structure, this doesn't guarantee
* that we have no leak.
*
* <p>
* So to further protect Jenkins, we pass through a fake {@link HttpServletRequest}
* that masks the values of the submission.
*
*
* <p>
* If the fake request is routed to {@link HttpGitRepository}, which is
* the only legitimate destination of the request, we'll unwrap this fake request
Expand All @@ -35,53 +35,51 @@
* <p>
* In this way, even if an attacker manages to route the request to elsewhere in Jenkins,
* that request will not be interpreted as a POST request.
*
*
* @author Kohsuke Kawaguchi
*/
@Extension
public class CSRFExclusionImpl extends CrumbExclusion {
private static final String BOGUS = "bogus";

public boolean process(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
if (!"application/x-git-receive-pack-request".equals(request.getHeader("Content-Type")))
return false;

// String path = request.getPathInfo();
// if(!path.contains("/repo.git/") || !path.endsWith("/git-receive-pack"))
// return false;
@Override
public boolean process(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws IOException, ServletException {
if (!"application/x-git-receive-pack-request".equals(request.getHeader("Content-Type"))) return false;

HttpServletRequestWrapper w = new HttpServletRequestWrapper(request) {
@Override
public String getQueryString() {
return "bogus";
return BOGUS;
}

@Override
public String getParameter(String name) {
return "bogus";
return BOGUS;
}

@Override
public Map getParameterMap() {
public Map<String, String[]> getParameterMap() {
return Collections.emptyMap();
}

@Override
public Enumeration getParameterNames() {
return new Vector().elements();
public Enumeration<String> getParameterNames() {
return Collections.emptyEnumeration();
}

@Override
public String[] getParameterValues(String name) {
return new String[]{"bogus"};
return new String[] {BOGUS};
}

@Override
public String getMethod() {
return "BOGUS";
return BOGUS.toUpperCase(Locale.ROOT);
}

@Override
public ServletInputStream getInputStream() throws IOException {
public ServletInputStream getInputStream() {
return new ServletInputStream() {
@Override
public boolean isFinished() {
Expand All @@ -94,7 +92,7 @@ public boolean isReady() {
}

@Override
public int read() throws IOException {
public int read() {
return -1;
}

Expand All @@ -105,13 +103,13 @@ public void setReadListener(ReadListener readListener) {
};
}
};
w.setAttribute(ORIGINAL_REQUEST,request);
chain.doFilter(w,response);
w.setAttribute(ORIGINAL_REQUEST, request);

chain.doFilter(w, response);
return true;
}

static final String ORIGINAL_REQUEST = CSRFExclusionImpl.class.getName()+".originalRequest";
static final String ORIGINAL_REQUEST = CSRFExclusionImpl.class.getName() + ".originalRequest";

public static HttpServletRequest unwrapRequest(HttpServletRequest req) {
return (HttpServletRequest) req.getAttribute(CSRFExclusionImpl.ORIGINAL_REQUEST);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
package org.jenkinsci.plugins.gitserver;

import hudson.FilePath;
import hudson.FilePath.FileCallable;
import hudson.remoting.Pipe;
import hudson.remoting.VirtualChannel;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import jenkins.MasterToSlaveFileCallable;
import org.apache.commons.io.IOUtils;
import org.eclipse.jgit.errors.NotSupportedException;
Expand All @@ -20,12 +24,6 @@
import org.eclipse.jgit.transport.URIish;
import org.eclipse.jgit.transport.UploadPack;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;

/**
* {@link Transport} implementation across pipes.
*
Expand All @@ -34,15 +32,14 @@
public class ChannelTransport extends Transport implements PackTransport {
private final FilePath remoteRepository;

public static Transport open(Repository local, FilePath remoteRepository) throws NotSupportedException, URISyntaxException, TransportException {
if (remoteRepository.isRemote())
return new ChannelTransport(local,remoteRepository);
else
return Transport.open(local,remoteRepository.getRemote());
public static Transport open(Repository local, FilePath remoteRepository)
throws NotSupportedException, URISyntaxException, TransportException {
if (remoteRepository.isRemote()) return new ChannelTransport(local, remoteRepository);
else return Transport.open(local, remoteRepository.getRemote());
}

public ChannelTransport(Repository local, FilePath remoteRepository) throws URISyntaxException {
super(local, new URIish("channel:"+remoteRepository.getRemote()));
super(local, new URIish("channel:" + remoteRepository.getRemote()));
this.remoteRepository = remoteRepository;
}

Expand All @@ -54,15 +51,18 @@ public FetchConnection openFetch() throws NotSupportedException, TransportExcept
try {
remoteRepository.actAsync(new GitFetchTask(l2r, r2l));
} catch (IOException e) {
throw new TransportException("Failed to open a fetch connection",e);
throw new TransportException("Failed to open a fetch connection", e);
} catch (InterruptedException e) {
throw new TransportException("Failed to open a fetch connection",e);
Thread.currentThread().interrupt();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does not appear to be related to the stated PR goal?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was flagged by the SonarQube for IDE in my IntelliJ IDEA (rule java:S1242). I've been fixing a bunch of other issues like this and so wanted to fix it here too. However, if you'd prefer it to be dropped, I can do so. I'm not stuck on getting that in.

throw new TransportException("Failed to open a fetch connection", e);
}

return new BasePackFetchConnection(this) {{
init(new BufferedInputStream(r2l.getIn()), new BufferedOutputStream(l2r.getOut()));
readAdvertisedRefs();
}};
return new BasePackFetchConnection(this) {
{
init(new BufferedInputStream(r2l.getIn()), new BufferedOutputStream(l2r.getOut()));
readAdvertisedRefs();
}
};
}

@Override
Expand All @@ -73,15 +73,18 @@ public PushConnection openPush() throws NotSupportedException, TransportExceptio
try {
remoteRepository.actAsync(new GitPushTask(l2r, r2l));
} catch (IOException e) {
throw new TransportException("Failed to open a fetch connection",e);
throw new TransportException("Failed to open a fetch connection", e);
} catch (InterruptedException e) {
throw new TransportException("Failed to open a fetch connection",e);
Thread.currentThread().interrupt();
throw new TransportException("Failed to open a fetch connection", e);
}

return new BasePackPushConnection(this) {{
init(new BufferedInputStream(r2l.getIn()), new BufferedOutputStream(l2r.getOut()));
readAdvertisedRefs();
}};
return new BasePackPushConnection(this) {
{
init(new BufferedInputStream(r2l.getIn()), new BufferedOutputStream(l2r.getOut()));
readAdvertisedRefs();
}
};
}

@Override
Expand All @@ -99,15 +102,13 @@ public GitFetchTask(Pipe l2r, Pipe r2l) {
}

public Void invoke(File f, VirtualChannel channel) throws IOException, InterruptedException {
Repository repo = new FileRepositoryBuilder().setWorkTree(f).build();
try {
try (Repository repo = new FileRepositoryBuilder().setWorkTree(f).build()) {
final UploadPack rp = new UploadPack(repo);
rp.upload(new BufferedInputStream(l2r.getIn()), new BufferedOutputStream(r2l.getOut()), null);
return null;
} finally {
IOUtils.closeQuietly(l2r.getIn());
IOUtils.closeQuietly(r2l.getOut());
repo.close();
}
}
}
Expand All @@ -122,15 +123,13 @@ public GitPushTask(Pipe l2r, Pipe r2l) {
}

public Void invoke(File f, VirtualChannel channel) throws IOException, InterruptedException {
Repository repo = new FileRepositoryBuilder().setWorkTree(f).build();
try {
try (Repository repo = new FileRepositoryBuilder().setWorkTree(f).build()) {
final ReceivePack rp = new ReceivePack(repo);
rp.receive(new BufferedInputStream(l2r.getIn()), new BufferedOutputStream(r2l.getOut()), null);
return null;
} finally {
IOUtils.closeQuietly(l2r.getIn());
IOUtils.closeQuietly(r2l.getOut());
repo.close();
}
}
}
Expand Down
Loading