/*
 * Copyright (C) 2011, Robin Rosenberg <robin.rosenberg@dewire.com>
 * 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 org.eclipse.jgit.lib;

import static java.nio.charset.StandardCharsets.UTF_8;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.io.File;
import java.io.IOException;
import java.util.Arrays;

import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.dircache.InvalidPathException;
import org.eclipse.jgit.junit.MockSystemReader;
import org.eclipse.jgit.junit.RepositoryTestCase;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.util.SystemReader;
import org.junit.Test;

public class DirCacheCheckoutMaliciousPathTest extends RepositoryTestCase {

	protected ObjectId theHead;
	protected ObjectId theMerge;

	@Test
	public void testMaliciousAbsolutePathIsOk() throws Exception {
		testMaliciousPathGoodFirstCheckout("ok");
	}

	@Test
	public void testMaliciousAbsolutePathIsOkSecondCheckout() throws Exception {
		testMaliciousPathGoodSecondCheckout("ok");
	}

	@Test
	public void testMaliciousAbsolutePathIsOkTwoLevels() throws Exception {
		testMaliciousPathGoodSecondCheckout("a", "ok");
	}

	@Test
	public void testMaliciousAbsolutePath() throws Exception {
		testMaliciousPathBadFirstCheckout("/tmp/x");
	}

	@Test
	public void testMaliciousAbsolutePathSecondCheckout() throws Exception {
		testMaliciousPathBadSecondCheckout("/tmp/x");
	}

	@Test
	public void testMaliciousAbsolutePathTwoLevelsFirstBad() throws Exception {
		testMaliciousPathBadFirstCheckout("/tmp/x", "y");
	}

	@Test
	public void testMaliciousAbsolutePathTwoLevelsSecondBad() throws Exception {
		testMaliciousPathBadFirstCheckout("y", "/tmp/x");
	}

	@Test
	public void testMaliciousAbsoluteCurDrivePathWindows() throws Exception {
		((MockSystemReader) SystemReader.getInstance()).setWindows();
		testMaliciousPathBadFirstCheckout("\\somepath");
	}

	@Test
	public void testMaliciousAbsoluteCurDrivePathWindowsOnUnix()
			throws Exception {
		((MockSystemReader) SystemReader.getInstance()).setUnix();
		testMaliciousPathGoodFirstCheckout("\\somepath");
	}

	@Test
	public void testMaliciousAbsoluteUNCPathWindows1() throws Exception {
		((MockSystemReader) SystemReader.getInstance()).setWindows();
		testMaliciousPathBadFirstCheckout("\\\\somepath");
	}

	@Test
	public void testMaliciousAbsoluteUNCPathWindows1OnUnix() throws Exception {
		((MockSystemReader) SystemReader.getInstance()).setUnix();
		testMaliciousPathGoodFirstCheckout("\\\\somepath");
	}

	@Test
	public void testMaliciousAbsoluteUNCPathWindows2() throws Exception {
		((MockSystemReader) SystemReader.getInstance()).setWindows();
		testMaliciousPathBadFirstCheckout("\\/somepath");
	}

	@Test
	public void testMaliciousAbsoluteUNCPathWindows2OnUnix() throws Exception {
		((MockSystemReader) SystemReader.getInstance()).setUnix();
		testMaliciousPathBadFirstCheckout("\\/somepath");
	}

	@Test
	public void testMaliciousAbsoluteWindowsPath1() throws Exception {
		((MockSystemReader) SystemReader.getInstance()).setWindows();
		testMaliciousPathBadFirstCheckout("c:\\temp\\x");
	}

	@Test
	public void testMaliciousAbsoluteWindowsPath1OnUnix() throws Exception {
		if (File.separatorChar == '\\')
			return; // cannot emulate Unix on Windows for this test
		((MockSystemReader) SystemReader.getInstance()).setUnix();
		testMaliciousPathGoodFirstCheckout("c:\\temp\\x");
	}

	@Test
	public void testMaliciousAbsoluteWindowsPath2() throws Exception {
		((MockSystemReader) SystemReader.getInstance()).setCurrentPlatform();
		testMaliciousPathBadFirstCheckout("c:/temp/x");
	}

	@Test
	public void testMaliciousGitPath1() throws Exception {
		testMaliciousPathBadFirstCheckout(".git/konfig");
	}

	@Test
	public void testMaliciousGitPath2() throws Exception {
		testMaliciousPathBadFirstCheckout(".git", "konfig");
	}

	@Test
	public void testMaliciousGitPath1Case() throws Exception {
		((MockSystemReader) SystemReader.getInstance()).setWindows(); // or OS X
		testMaliciousPathBadFirstCheckout(".Git/konfig");
	}

	@Test
	public void testMaliciousGitPath2Case() throws Exception {
		((MockSystemReader) SystemReader.getInstance()).setWindows(); // or OS X
		testMaliciousPathBadFirstCheckout(".gIt", "konfig");
	}

	@Test
	public void testMaliciousGitPath3Case() throws Exception {
		((MockSystemReader) SystemReader.getInstance()).setWindows(); // or OS X
		testMaliciousPathBadFirstCheckout(".giT", "konfig");
	}

	@Test
	public void testMaliciousGitPathEndSpaceWindows() throws Exception {
		((MockSystemReader) SystemReader.getInstance()).setWindows();
		testMaliciousPathBadFirstCheckout(".git ", "konfig");
	}

	@Test
	public void testMaliciousGitPathEndSpaceUnixOk() throws Exception {
		testMaliciousPathBadFirstCheckout(".git ", "konfig");
	}

	@Test
	public void testMaliciousGitPathEndDotWindows1() throws Exception {
		((MockSystemReader) SystemReader.getInstance()).setWindows();
		testMaliciousPathBadFirstCheckout(".git.", "konfig");
	}

	@Test
	public void testMaliciousGitPathEndDotWindows2() throws Exception {
		((MockSystemReader) SystemReader.getInstance()).setWindows();
		testMaliciousPathBadFirstCheckout(".f.");
	}

	@Test
	public void testMaliciousGitPathEndDotWindows3() throws Exception {
		((MockSystemReader) SystemReader.getInstance()).setWindows();
		testMaliciousPathGoodFirstCheckout(".f");
	}

	@Test
	public void testMaliciousGitPathEndDotUnixOk() throws Exception {
		testMaliciousPathBadFirstCheckout(".git.", "konfig");
	}

	@Test
	public void testMaliciousPathDotDot() throws Exception {
		((MockSystemReader) SystemReader.getInstance()).setCurrentPlatform();
		testMaliciousPathBadFirstCheckout("..", "no");
	}

	@Test
	public void testMaliciousPathDot() throws Exception {
		((MockSystemReader) SystemReader.getInstance()).setCurrentPlatform();
		testMaliciousPathBadFirstCheckout(".", "no");
	}

	@Test
	public void testMaliciousPathEmptyUnix() throws Exception {
		((MockSystemReader) SystemReader.getInstance()).setUnix();
		testMaliciousPathBadFirstCheckout("", "no");
	}

	@Test
	public void testMaliciousPathEmptyWindows() throws Exception {
		((MockSystemReader) SystemReader.getInstance()).setWindows();
		testMaliciousPathBadFirstCheckout("", "no");
	}

	@Test
	public void testMaliciousWindowsADS() throws Exception {
		((MockSystemReader) SystemReader.getInstance()).setWindows();
		testMaliciousPathBadFirstCheckout("some:path");
	}

	@Test
	public void testMaliciousWindowsADSOnUnix() throws Exception {
		if (File.separatorChar == '\\')
			return; // cannot emulate Unix on Windows for this test
		((MockSystemReader) SystemReader.getInstance()).setUnix();
		testMaliciousPathGoodFirstCheckout("some:path");
	}

	@Test
	public void testForbiddenNamesOnWindowsEgCon() throws Exception {
		((MockSystemReader) SystemReader.getInstance()).setWindows();
		testMaliciousPathBadFirstCheckout("con");
	}

	@Test
	public void testForbiddenNamesOnWindowsEgConDotSuffix() throws Exception {
		((MockSystemReader) SystemReader.getInstance()).setWindows();
		testMaliciousPathBadFirstCheckout("con.txt");
	}

	@Test
	public void testForbiddenNamesOnWindowsEgLpt1() throws Exception {
		((MockSystemReader) SystemReader.getInstance()).setWindows();
		testMaliciousPathBadFirstCheckout("lpt1");
	}

	@Test
	public void testForbiddenNamesOnWindowsEgLpt1DotSuffix() throws Exception {
		((MockSystemReader) SystemReader.getInstance()).setWindows();
		testMaliciousPathBadFirstCheckout("lpt1.txt");
	}

	@Test
	public void testForbiddenNamesOnWindowsEgDotCon() throws Exception {
		((MockSystemReader) SystemReader.getInstance()).setWindows();
		testMaliciousPathGoodFirstCheckout(".con");
	}

	@Test
	public void testForbiddenNamesOnWindowsEgLpr() throws Exception {
		((MockSystemReader) SystemReader.getInstance()).setWindows();
		testMaliciousPathGoodFirstCheckout("lpt"); // good name
	}

	@Test
	public void testForbiddenNamesOnWindowsEgCon1() throws Exception {
		((MockSystemReader) SystemReader.getInstance()).setWindows();
		testMaliciousPathGoodFirstCheckout("con1"); // good name
	}

	@Test
	public void testForbiddenWindowsNamesOnUnixEgCon() throws Exception {
		if (File.separatorChar == '\\')
			return; // cannot emulate Unix on Windows for this test
		testMaliciousPathGoodFirstCheckout("con");
	}

	@Test
	public void testForbiddenWindowsNamesOnUnixEgLpt1() throws Exception {
		if (File.separatorChar == '\\')
			return; // cannot emulate Unix on Windows for this test
		testMaliciousPathGoodFirstCheckout("lpt1");
	}

	private void testMaliciousPathBadFirstCheckout(String... paths)
			throws Exception {
		testMaliciousPath(false, false, paths);
	}

	private void testMaliciousPathBadSecondCheckout(String... paths) throws Exception {
		testMaliciousPath(false, true, paths);
	}

	private void testMaliciousPathGoodFirstCheckout(String... paths)
			throws Exception {
		testMaliciousPath(true, false, paths);
	}

	private void testMaliciousPathGoodSecondCheckout(String... paths) throws Exception {
		testMaliciousPath(true, true, paths);
	}

	/**
	 * Create a bad tree and tries to check it out
	 *
	 * @param good
	 *            true if we expect this to pass
	 * @param secondCheckout
	 *            perform the actual test on the second checkout
	 * @param path
	 *            to the blob, one or more levels
	 * @throws GitAPIException
	 * @throws IOException
	 */
	private void testMaliciousPath(boolean good, boolean secondCheckout,
			String... path) throws GitAPIException, IOException {
		try (Git git = new Git(db);
				RevWalk revWalk = new RevWalk(git.getRepository())) {
			ObjectInserter newObjectInserter;
			newObjectInserter = git.getRepository().newObjectInserter();
			ObjectId blobId = newObjectInserter.insert(Constants.OBJ_BLOB,
					"data".getBytes(UTF_8));
			newObjectInserter = git.getRepository().newObjectInserter();
			FileMode mode = FileMode.REGULAR_FILE;
			ObjectId insertId = blobId;
			for (int i = path.length - 1; i >= 0; --i) {
				TreeFormatter treeFormatter = new TreeFormatter();
				treeFormatter.append("goodpath", mode, insertId);
				insertId = newObjectInserter.insert(treeFormatter);
				mode = FileMode.TREE;
			}
			newObjectInserter = git.getRepository().newObjectInserter();
			CommitBuilder commitBuilder = new CommitBuilder();
			commitBuilder.setAuthor(author);
			commitBuilder.setCommitter(committer);
			commitBuilder.setMessage("foo#1");
			commitBuilder.setTreeId(insertId);
			ObjectId firstCommitId = newObjectInserter.insert(commitBuilder);

			newObjectInserter = git.getRepository().newObjectInserter();
			mode = FileMode.REGULAR_FILE;
			insertId = blobId;
			for (int i = path.length - 1; i >= 0; --i) {
				TreeFormatter treeFormatter = new TreeFormatter();
				treeFormatter.append(path[i].getBytes(UTF_8), 0,
						path[i].getBytes(UTF_8).length,
							mode, insertId, true);
				insertId = newObjectInserter.insert(treeFormatter);
				mode = FileMode.TREE;
			}

			// Create another commit
			commitBuilder = new CommitBuilder();
			commitBuilder.setAuthor(author);
			commitBuilder.setCommitter(committer);
			commitBuilder.setMessage("foo#2");
			commitBuilder.setTreeId(insertId);
			commitBuilder.setParentId(firstCommitId);
			ObjectId commitId = newObjectInserter.insert(commitBuilder);

			if (!secondCheckout)
				git.checkout().setStartPoint(revWalk.parseCommit(firstCommitId))
						.setName("refs/heads/master").setCreateBranch(true).call();
			try {
				if (secondCheckout) {
					git.checkout().setStartPoint(revWalk.parseCommit(commitId))
							.setName("refs/heads/master").setCreateBranch(true)
							.call();
				} else {
					git.branchCreate().setName("refs/heads/next")
							.setStartPoint(commitId.name()).call();
					git.checkout().setName("refs/heads/next")
							.call();
				}
				if (!good)
					fail("Checkout of Tree " + Arrays.asList(path) + " should fail");
			} catch (InvalidPathException e) {
				if (good)
					throw e;
				assertTrue(e.getMessage().startsWith("Invalid path"));
			}
		}
	}

}
