/*
 * Copyright (C) 2015, Google Inc.
 *
 * 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.transport;

import static java.nio.charset.StandardCharsets.UTF_8;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.io.ByteArrayInputStream;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringReader;

import org.eclipse.jgit.errors.PackProtocolException;
import org.eclipse.jgit.internal.storage.dfs.DfsRepositoryDescription;
import org.eclipse.jgit.internal.storage.dfs.InMemoryRepository;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.transport.PushCertificate.NonceStatus;
import org.junit.Before;
import org.junit.Test;

/** Test for push certificate parsing. */
public class PushCertificateParserTest {
	// Example push certificate generated by C git 2.2.0.
	private static final String INPUT = "001ccertificate version 0.1\n"
			+ "0041pusher Dave Borowitz <dborowitz@google.com> 1433954361 -0700\n"
			+ "0024pushee git://localhost/repo.git\n"
			+ "002anonce 1433954361-bde756572d665bba81d8\n"
			+ "0005\n"
			+ "00680000000000000000000000000000000000000000"
			+ " 6c2b981a177396fb47345b7df3e4d3f854c6bea7"
			+ " refs/heads/master\n"
			+ "0022-----BEGIN PGP SIGNATURE-----\n"
			+ "0016Version: GnuPG v1\n"
			+ "0005\n"
			+ "0045iQEcBAABAgAGBQJVeGg5AAoJEPfTicJkUdPkUggH/RKAeI9/i/LduuiqrL/SSdIa\n"
			+ "00459tYaSqJKLbXz63M/AW4Sp+4u+dVCQvnAt/a35CVEnpZz6hN4Kn/tiswOWVJf4CO7\n"
			+ "0045htNubGs5ZMwvD6sLYqKAnrM3WxV/2TbbjzjZW6Jkidz3jz/WRT4SmjGYiEO7aA+V\n"
			+ "00454ZdIS9f7sW5VsHHYlNThCA7vH8Uu48bUovFXyQlPTX0pToSgrWV3JnTxDNxfn3iG\n"
			+ "0045IL0zTY/qwVCdXgFownLcs6J050xrrBWIKqfcWr3u4D2aCLyR0v+S/KArr7ulZygY\n"
			+ "0045+SOklImn8TAZiNxhWtA6ens66IiammUkZYFv7SSzoPLFZT4dC84SmGPWgf94NoQ=\n"
			+ "000a=XFeC\n"
			+ "0020-----END PGP SIGNATURE-----\n"
			+ "0012push-cert-end\n";

	// Same push certificate, with all trailing newlines stripped.
	// (Note that the canonical signed payload is the same, so the same signature
	// is still valid.)
	private static final String INPUT_NO_NEWLINES = "001bcertificate version 0.1"
			+ "0040pusher Dave Borowitz <dborowitz@google.com> 1433954361 -0700"
			+ "0023pushee git://localhost/repo.git"
			+ "0029nonce 1433954361-bde756572d665bba81d8"
			+ "0004"
			+ "00670000000000000000000000000000000000000000"
			+ " 6c2b981a177396fb47345b7df3e4d3f854c6bea7"
			+ " refs/heads/master"
			+ "0021-----BEGIN PGP SIGNATURE-----"
			+ "0015Version: GnuPG v1"
			+ "0004"
			+ "0044iQEcBAABAgAGBQJVeGg5AAoJEPfTicJkUdPkUggH/RKAeI9/i/LduuiqrL/SSdIa"
			+ "00449tYaSqJKLbXz63M/AW4Sp+4u+dVCQvnAt/a35CVEnpZz6hN4Kn/tiswOWVJf4CO7"
			+ "0044htNubGs5ZMwvD6sLYqKAnrM3WxV/2TbbjzjZW6Jkidz3jz/WRT4SmjGYiEO7aA+V"
			+ "00444ZdIS9f7sW5VsHHYlNThCA7vH8Uu48bUovFXyQlPTX0pToSgrWV3JnTxDNxfn3iG"
			+ "0044IL0zTY/qwVCdXgFownLcs6J050xrrBWIKqfcWr3u4D2aCLyR0v+S/KArr7ulZygY"
			+ "0044+SOklImn8TAZiNxhWtA6ens66IiammUkZYFv7SSzoPLFZT4dC84SmGPWgf94NoQ="
			+ "0009=XFeC"
			+ "001f-----END PGP SIGNATURE-----"
			+ "0011push-cert-end";

	private Repository db;

	@Before
	public void setUp() {
		db = new InMemoryRepository(new DfsRepositoryDescription("repo"));
	}

	private static SignedPushConfig newEnabledConfig() {
		Config cfg = new Config();
		cfg.setString("receive", null, "certnonceseed", "sekret");
		return SignedPushConfig.KEY.parse(cfg);
	}

	private static SignedPushConfig newDisabledConfig() {
		return SignedPushConfig.KEY.parse(new Config());
	}

	@Test
	public void noCert() throws Exception {
		PushCertificateParser parser =
				new PushCertificateParser(db, newEnabledConfig());
		assertTrue(parser.enabled());
		assertNull(parser.build());

		ObjectId oldId = ObjectId.zeroId();
		ObjectId newId =
				ObjectId.fromString("deadbeefdeadbeefdeadbeefdeadbeefdeadbeef");
		String line = oldId.name() + " " + newId.name() + " refs/heads/master";
		ReceiveCommand cmd = ReceivePack.parseCommand(line);

		parser.addCommand(cmd);
		parser.addCommand(line);
		assertNull(parser.build());
	}

	@Test
	public void disabled() throws Exception {
		PacketLineIn pckIn = newPacketLineIn(INPUT);
		PushCertificateParser parser =
				new PushCertificateParser(db, newDisabledConfig());
		assertFalse(parser.enabled());
		assertNull(parser.build());

		parser.receiveHeader(pckIn, false);
		parser.addCommand(pckIn.readString());
		assertEquals(PushCertificateParser.BEGIN_SIGNATURE, pckIn.readString());
		parser.receiveSignature(pckIn);
		assertNull(parser.build());
	}

	@Test
	public void disabledParserStillRequiresCorrectSyntax() throws Exception {
		PacketLineIn pckIn = newPacketLineIn("001ccertificate version XYZ\n");
		PushCertificateParser parser =
				new PushCertificateParser(db, newDisabledConfig());
		assertFalse(parser.enabled());
		try {
			parser.receiveHeader(pckIn, false);
			fail("Expected PackProtocolException");
		} catch (PackProtocolException e) {
			assertEquals(
					"Push certificate has missing or invalid value for certificate"
						+ " version: XYZ",
					e.getMessage());
		}
		assertNull(parser.build());
	}

	@Test
	public void parseCertFromPktLine() throws Exception {
		PacketLineIn pckIn = newPacketLineIn(INPUT);
		PushCertificateParser parser =
				new PushCertificateParser(db, newEnabledConfig());
		parser.receiveHeader(pckIn, false);
		parser.addCommand(pckIn.readString());
		assertEquals(PushCertificateParser.BEGIN_SIGNATURE, pckIn.readString());
		parser.receiveSignature(pckIn);

		PushCertificate cert = parser.build();
		assertEquals("0.1", cert.getVersion());
		assertEquals("Dave Borowitz", cert.getPusherIdent().getName());
		assertEquals("dborowitz@google.com",
				cert.getPusherIdent().getEmailAddress());
		assertEquals(1433954361000L, cert.getPusherIdent().getWhen().getTime());
		assertEquals(-7 * 60, cert.getPusherIdent().getTimeZoneOffset());
		assertEquals("git://localhost/repo.git", cert.getPushee());
		assertEquals("1433954361-bde756572d665bba81d8", cert.getNonce());

		assertNotEquals(cert.getNonce(), parser.getAdvertiseNonce());
		assertEquals(PushCertificate.NonceStatus.BAD, cert.getNonceStatus());

		assertEquals(1, cert.getCommands().size());
		ReceiveCommand cmd = cert.getCommands().get(0);
		assertEquals("refs/heads/master", cmd.getRefName());
		assertEquals(ObjectId.zeroId(), cmd.getOldId());
		assertEquals("6c2b981a177396fb47345b7df3e4d3f854c6bea7",
				cmd.getNewId().name());

		assertEquals(concatPacketLines(INPUT, 0, 6), cert.toText());
		assertEquals(concatPacketLines(INPUT, 0, 17), cert.toTextWithSignature());

		String signature = concatPacketLines(INPUT, 6, 17);
		assertTrue(signature.startsWith(PushCertificateParser.BEGIN_SIGNATURE));
		assertTrue(signature.endsWith(PushCertificateParser.END_SIGNATURE + "\n"));
		assertEquals(signature, cert.getSignature());
	}

	@Test
	public void parseCertFromPktLineNoNewlines() throws Exception {
		PacketLineIn pckIn = newPacketLineIn(INPUT_NO_NEWLINES);
		PushCertificateParser parser =
				new PushCertificateParser(db, newEnabledConfig());
		parser.receiveHeader(pckIn, false);
		parser.addCommand(pckIn.readString());
		assertEquals(PushCertificateParser.BEGIN_SIGNATURE, pckIn.readString());
		parser.receiveSignature(pckIn);

		PushCertificate cert = parser.build();
		assertEquals("0.1", cert.getVersion());
		assertEquals("Dave Borowitz", cert.getPusherIdent().getName());
		assertEquals("dborowitz@google.com",
				cert.getPusherIdent().getEmailAddress());
		assertEquals(1433954361000L, cert.getPusherIdent().getWhen().getTime());
		assertEquals(-7 * 60, cert.getPusherIdent().getTimeZoneOffset());
		assertEquals("git://localhost/repo.git", cert.getPushee());
		assertEquals("1433954361-bde756572d665bba81d8", cert.getNonce());

		assertNotEquals(cert.getNonce(), parser.getAdvertiseNonce());
		assertEquals(PushCertificate.NonceStatus.BAD, cert.getNonceStatus());

		assertEquals(1, cert.getCommands().size());
		ReceiveCommand cmd = cert.getCommands().get(0);
		assertEquals("refs/heads/master", cmd.getRefName());
		assertEquals(ObjectId.zeroId(), cmd.getOldId());
		assertEquals("6c2b981a177396fb47345b7df3e4d3f854c6bea7",
				cmd.getNewId().name());

		// Canonical signed payload has reinserted newlines.
		assertEquals(concatPacketLines(INPUT, 0, 6), cert.toText());

		String signature = concatPacketLines(INPUT, 6, 17);
		assertTrue(signature.startsWith(PushCertificateParser.BEGIN_SIGNATURE));
		assertTrue(signature.endsWith(PushCertificateParser.END_SIGNATURE + "\n"));
		assertEquals(signature, cert.getSignature());
	}

	@Test
	public void testConcatPacketLines() throws Exception {
		String input = "000bline 1\n000bline 2\n000bline 3\n";
		assertEquals("line 1\n", concatPacketLines(input, 0, 1));
		assertEquals("line 1\nline 2\n", concatPacketLines(input, 0, 2));
		assertEquals("line 2\nline 3\n", concatPacketLines(input, 1, 3));
		assertEquals("line 2\nline 3\n", concatPacketLines(input, 1, 4));
	}

	@Test
	public void testConcatPacketLinesInsertsNewlines() throws Exception {
		String input = "000bline 1\n000aline 2000bline 3\n";
		assertEquals("line 1\n", concatPacketLines(input, 0, 1));
		assertEquals("line 1\nline 2\n", concatPacketLines(input, 0, 2));
		assertEquals("line 2\nline 3\n", concatPacketLines(input, 1, 3));
		assertEquals("line 2\nline 3\n", concatPacketLines(input, 1, 4));
	}

	@Test
	public void testParseReader() throws Exception {
		Reader reader = new StringReader(concatPacketLines(INPUT, 0, 18));
		PushCertificate streamCert = PushCertificateParser.fromReader(reader);

		PacketLineIn pckIn = newPacketLineIn(INPUT);
		PushCertificateParser pckParser =
				new PushCertificateParser(db, newEnabledConfig());
		pckParser.receiveHeader(pckIn, false);
		pckParser.addCommand(pckIn.readString());
		assertEquals(PushCertificateParser.BEGIN_SIGNATURE, pckIn.readString());
		pckParser.receiveSignature(pckIn);
		PushCertificate pckCert = pckParser.build();

		// Nonce status is unsolicited since this was not parsed in the context of
		// the wire protocol; as a result, certs are not actually equal.
		assertEquals(NonceStatus.UNSOLICITED, streamCert.getNonceStatus());

		assertEquals(pckCert.getVersion(), streamCert.getVersion());
		assertEquals(pckCert.getPusherIdent().getName(),
				streamCert.getPusherIdent().getName());
		assertEquals(pckCert.getPusherIdent().getEmailAddress(),
				streamCert.getPusherIdent().getEmailAddress());
		assertEquals(pckCert.getPusherIdent().getWhen().getTime(),
				streamCert.getPusherIdent().getWhen().getTime());
		assertEquals(pckCert.getPusherIdent().getTimeZoneOffset(),
				streamCert.getPusherIdent().getTimeZoneOffset());
		assertEquals(pckCert.getPushee(), streamCert.getPushee());
		assertEquals(pckCert.getNonce(), streamCert.getNonce());
		assertEquals(pckCert.getSignature(), streamCert.getSignature());
		assertEquals(pckCert.toText(), streamCert.toText());

		assertEquals(pckCert.getCommands().size(), streamCert.getCommands().size());
		ReceiveCommand pckCmd = pckCert.getCommands().get(0);
		ReceiveCommand streamCmd = streamCert.getCommands().get(0);
		assertEquals(pckCmd.getRefName(), streamCmd.getRefName());
		assertEquals(pckCmd.getOldId(), streamCmd.getOldId());
		assertEquals(pckCmd.getNewId().name(), streamCmd.getNewId().name());
	}

	@Test
	public void testParseString() throws Exception {
		String str = concatPacketLines(INPUT, 0, 18);
		assertEquals(
				PushCertificateParser.fromReader(new StringReader(str)),
				PushCertificateParser.fromString(str));
	}

	@Test
	public void testParseMultipleFromStream() throws Exception {
		String input = concatPacketLines(INPUT, 0, 17);
		assertFalse(input.contains(PushCertificateParser.END_CERT));
		input += input;
		Reader reader = new InputStreamReader(
				new ByteArrayInputStream(Constants.encode(input)), UTF_8);

		assertNotNull(PushCertificateParser.fromReader(reader));
		assertNotNull(PushCertificateParser.fromReader(reader));
		assertEquals(-1, reader.read());
		assertNull(PushCertificateParser.fromReader(reader));
	}

	@Test
	public void testMissingPusheeField() throws Exception {
		// Omit pushee line from existing cert. (This means the signature would not
		// match, but we're not verifying it here.)
		String input = INPUT.replace("0024pushee git://localhost/repo.git\n", "");
		assertFalse(input.contains(PushCertificateParser.PUSHEE));

		PacketLineIn pckIn = newPacketLineIn(input);
		PushCertificateParser parser =
				new PushCertificateParser(db, newEnabledConfig());
		parser.receiveHeader(pckIn, false);
		parser.addCommand(pckIn.readString());
		assertEquals(PushCertificateParser.BEGIN_SIGNATURE, pckIn.readString());
		parser.receiveSignature(pckIn);

		PushCertificate cert = parser.build();
		assertEquals("0.1", cert.getVersion());
		assertNull(cert.getPushee());
		assertFalse(cert.toText().contains(PushCertificateParser.PUSHEE));
	}

	private static String concatPacketLines(String input, int begin, int end)
			throws IOException {
		StringBuilder result = new StringBuilder();
		int i = 0;
		PacketLineIn pckIn = newPacketLineIn(input);
		while (i < end) {
			String line;
			try {
				line = pckIn.readString();
			} catch (EOFException e) {
				break;
			}
			if (++i > begin) {
				result.append(line).append('\n');
			}
		}
		return result.toString();
	}

	private static PacketLineIn newPacketLineIn(String input) {
		return new PacketLineIn(new ByteArrayInputStream(Constants.encode(input)));
	}
}
