Skip to content

Instantly share code, notes, and snippets.

@sdorra
Created April 29, 2020 19:33
Show Gist options
  • Select an option

  • Save sdorra/b9f4374583c1b15b79f15354a78a4e05 to your computer and use it in GitHub Desktop.

Select an option

Save sdorra/b9f4374583c1b15b79f15354a78a4e05 to your computer and use it in GitHub Desktop.

Revisions

  1. sdorra created this gist Apr 29, 2020.
    65 changes: 65 additions & 0 deletions CorruptingProxy.groovy
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,65 @@
    @Grab(group='org.eclipse.jetty', module='jetty-server', version='9.1.6.v20160112')
    @Grab(group='org.eclipse.jetty', module='jetty-servlet', version='9.1.6.v20160112')
    @Grab(group='org.eclipse.jetty', module='jetty-proxy', version='9.1.6.v20160112')
    @Grab(group='com.google.guava', module='guava', version='29.0-jre')

    import com.google.common.io.ByteStreams;
    import org.eclipse.jetty.client.api.Request;
    import org.eclipse.jetty.client.util.BytesContentProvider;
    import org.eclipse.jetty.proxy.ProxyServlet;
    import org.eclipse.jetty.server.Server;
    import org.eclipse.jetty.servlet.ServletContextHandler;
    import org.eclipse.jetty.servlet.ServletHolder;

    import javax.servlet.ServletInputStream;
    import javax.servlet.http.HttpServletRequest;
    import java.io.IOException;

    public class SvnProtocolProxy extends ProxyServlet.Transparent {

    @Override
    protected void customizeProxyRequest(Request proxyRequest, HttpServletRequest request) {
    if (isSvnPutRequest(request)) {
    try (ServletInputStream inputStream = request.getInputStream()) {
    byte[] original = ByteStreams.toByteArray(inputStream);
    byte[] corrupted = new byte[original.length];

    for (int i = 0; i < original.length; i++) {
    char c = (char) original[i];
    if (c == 'a') {
    corrupted[i] = 'z';
    } else {
    corrupted[i] = original[i];
    }
    }

    byte[][] chunks = new byte[][]{
    corrupted
    };

    proxyRequest.content(new BytesContentProvider(chunks));
    } catch (IOException ex) {
    ex.printStackTrace(System.err);
    }
    }
    }

    private boolean isSvnPutRequest(HttpServletRequest request) {
    return "PUT".equalsIgnoreCase(request.getMethod())
    && request.getHeader("X-SVN-Result-Fulltext-MD5") != null;
    }

    }

    Server server = new Server(8000);

    ServletHolder proxyServlet = new ServletHolder(SvnProtocolProxy.class);
    proxyServlet.setInitParameter("proxyTo", "http://localhost:8080/");
    proxyServlet.setInitParameter("prefix", "/");

    ServletContextHandler context = new ServletContextHandler();
    context.addServlet(proxyServlet, "/*");

    server.setHandler(context);
    server.start();
    server.join();
    36 changes: 36 additions & 0 deletions verify.sh
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,36 @@
    # first we have to create an svn repository via scm-manager
    # in the following example we assume the repository scmadmin/hitchhiker was created
    $ svn checkout http://localhost:8000/scm/repo/scmadmin/hitchhiker
    $ cd hitchhiker
    $ echo a > a.txt
    $ svn add a.txt

    # the corrupting proxy will replace the content of 'a' with 'z'
    $ svn commit -m 'added a.txt'
    Adding a.txt
    Transmitting file data .done
    Committing transaction...
    Committed revision 1.

    # the local copy contains 'a' but the server has 'z'
    $ svn commit -m 'update a.txt'
    Sending a.txt
    Transmitting file data .svn: E200014: Commit failed (details follow):
    svn: E200014: svn: E200014: Base checksum mismatch on '/a.txt':
    expected: 60b725f10c9c85c70d97880dfe8191b3
    actual: a8a78d0ff555c931f045b6f448129846

    $ cd ..
    $ rm -rf hitchhiker
    $ svn checkout http://localhost:8000/scm/repo/scmadmin/hitchhiker
    A hitchhiker/a.txt
    Checked out revision 1.

    $ cat hitchhiker/a.txt
    z

    # but the repository on the server side does not know about the corruption
    $ svnadmin verify ${SCM_HOME}/repositories/idOfRepository/data
    * Verifying repository metadata ...
    * Verified revision 0.
    * Verified revision 1.