/*
 * 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 = BaseReceivePack.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)));
	}
}
