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

import static org.eclipse.jgit.transport.ReceivePack.parseCommand;
import static org.eclipse.jgit.transport.GitProtocolConstants.CAPABILITY_PUSH_CERT;

import java.io.EOFException;
import java.io.IOException;
import java.io.Reader;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;

import org.eclipse.jgit.errors.PackProtocolException;
import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.transport.PushCertificate.NonceStatus;
import org.eclipse.jgit.util.IO;

/**
 * Parser for signed push certificates.
 *
 * @since 4.0
 */
public class PushCertificateParser {
	static final String BEGIN_SIGNATURE =
			"-----BEGIN PGP SIGNATURE-----"; //$NON-NLS-1$
	static final String END_SIGNATURE =
			"-----END PGP SIGNATURE-----"; //$NON-NLS-1$

	static final String VERSION = "certificate version"; //$NON-NLS-1$

	static final String PUSHER = "pusher"; //$NON-NLS-1$

	static final String PUSHEE = "pushee"; //$NON-NLS-1$

	static final String NONCE = "nonce"; //$NON-NLS-1$

	static final String END_CERT = "push-cert-end"; //$NON-NLS-1$

	private static final String VERSION_0_1 = "0.1"; //$NON-NLS-1$

	private static interface StringReader {
		/**
		 * @return the next string from the input, up to an optional newline, with
		 *         newline stripped if present
		 *
		 * @throws EOFException
		 *             if EOF was reached.
		 * @throws IOException
		 *             if an error occurred during reading.
		 */
		String read() throws EOFException, IOException;
	}

	private static class PacketLineReader implements StringReader {
		private final PacketLineIn pckIn;

		private PacketLineReader(PacketLineIn pckIn) {
			this.pckIn = pckIn;
		}

		@Override
		public String read() throws IOException {
			return pckIn.readString();
		}
	}

	private static class StreamReader implements StringReader {
		private final Reader reader;

		private StreamReader(Reader reader) {
			this.reader = reader;
		}

		@Override
		public String read() throws IOException {
			// Presize for a command containing 2 SHA-1s and some refname.
			String line = IO.readLine(reader, 41 * 2 + 64);
			if (line.isEmpty()) {
				throw new EOFException();
			} else if (line.charAt(line.length() - 1) == '\n') {
				line = line.substring(0, line.length() - 1);
			}
			return line;
		}
	}

	/**
	 * Parse a push certificate from a reader.
	 * <p>
	 * Differences from the {@link org.eclipse.jgit.transport.PacketLineIn}
	 * receiver methods:
	 * <ul>
	 * <li>Does not use pkt-line framing.</li>
	 * <li>Reads an entire cert in one call rather than depending on a loop in
	 * the caller.</li>
	 * <li>Does not assume a {@code "push-cert-end"} line.</li>
	 * </ul>
	 *
	 * @param r
	 *            input reader; consumed only up until the end of the next
	 *            signature in the input.
	 * @return the parsed certificate, or null if the reader was at EOF.
	 * @throws org.eclipse.jgit.errors.PackProtocolException
	 *             if the certificate is malformed.
	 * @throws java.io.IOException
	 *             if there was an error reading from the input.
	 * @since 4.1
	 */
	public static PushCertificate fromReader(Reader r)
			throws PackProtocolException, IOException {
		return new PushCertificateParser().parse(r);
	}

	/**
	 * Parse a push certificate from a string.
	 *
	 * @see #fromReader(Reader)
	 * @param str
	 *            input string.
	 * @return the parsed certificate.
	 * @throws org.eclipse.jgit.errors.PackProtocolException
	 *             if the certificate is malformed.
	 * @throws java.io.IOException
	 *             if there was an error reading from the input.
	 * @since 4.1
	 */
	public static PushCertificate fromString(String str)
			throws PackProtocolException, IOException {
		return fromReader(new java.io.StringReader(str));
	}

	private boolean received;
	private String version;
	private PushCertificateIdent pusher;
	private String pushee;

	/** The nonce that was sent to the client. */
	private String sentNonce;

	/**
	 * The nonce the pusher signed.
	 * <p>
	 * This may vary from {@link #sentNonce}; see git-core documentation for
	 * reasons.
	 */
	private String receivedNonce;

	private NonceStatus nonceStatus;
	private String signature;

	/** Database we write the push certificate into. */
	private final Repository db;

	/**
	 * The maximum time difference which is acceptable between advertised nonce
	 * and received signed nonce.
	 */
	private final int nonceSlopLimit;

	private final boolean enabled;
	private final NonceGenerator nonceGenerator;
	private final List<ReceiveCommand> commands = new ArrayList<>();

	/**
	 * <p>Constructor for PushCertificateParser.</p>
	 *
	 * @param into
	 *            destination repository for the push.
	 * @param cfg
	 *            configuration for signed push.
	 * @since 4.1
	 */
	public PushCertificateParser(Repository into, SignedPushConfig cfg) {
		if (cfg != null) {
			nonceSlopLimit = cfg.getCertNonceSlopLimit();
			nonceGenerator = cfg.getNonceGenerator();
		} else {
			nonceSlopLimit = 0;
			nonceGenerator = null;
		}
		db = into;
		enabled = nonceGenerator != null;
	}

	private PushCertificateParser() {
		db = null;
		nonceSlopLimit = 0;
		nonceGenerator = null;
		enabled = true;
	}

	/**
	 * Parse a push certificate from a reader.
	 *
	 * @see #fromReader(Reader)
	 * @param r
	 *            input reader; consumed only up until the end of the next
	 *            signature in the input.
	 * @return the parsed certificate, or null if the reader was at EOF.
	 * @throws org.eclipse.jgit.errors.PackProtocolException
	 *             if the certificate is malformed.
	 * @throws java.io.IOException
	 *             if there was an error reading from the input.
	 * @since 4.1
	 */
	public PushCertificate parse(Reader r)
			throws PackProtocolException, IOException {
		StreamReader reader = new StreamReader(r);
		receiveHeader(reader, true);
		String line;
		try {
			while (!(line = reader.read()).isEmpty()) {
				if (line.equals(BEGIN_SIGNATURE)) {
					receiveSignature(reader);
					break;
				}
				addCommand(line);
			}
		} catch (EOFException e) {
			// EOF reached, but might have been at a valid state. Let build call below
			// sort it out.
		}
		return build();
	}

	/**
	 * Build the parsed certificate
	 *
	 * @return the parsed certificate, or null if push certificates are
	 *         disabled.
	 * @throws java.io.IOException
	 *             if the push certificate has missing or invalid fields.
	 * @since 4.1
	 */
	public PushCertificate build() throws IOException {
		if (!received || !enabled) {
			return null;
		}
		try {
			return new PushCertificate(version, pusher, pushee, receivedNonce,
					nonceStatus, Collections.unmodifiableList(commands), signature);
		} catch (IllegalArgumentException e) {
			throw new IOException(e.getMessage(), e);
		}
	}

	/**
	 * Whether the repository is configured to use signed pushes in this
	 * context.
	 *
	 * @return if the repository is configured to use signed pushes in this
	 *         context.
	 * @since 4.0
	 */
	public boolean enabled() {
		return enabled;
	}

	/**
	 * Get the whole string for the nonce to be included into the capability
	 * advertisement
	 *
	 * @return the whole string for the nonce to be included into the capability
	 *         advertisement, or null if push certificates are disabled.
	 * @since 4.0
	 */
	public String getAdvertiseNonce() {
		String nonce = sentNonce();
		if (nonce == null) {
			return null;
		}
		return CAPABILITY_PUSH_CERT + '=' + nonce;
	}

	private String sentNonce() {
		if (sentNonce == null && nonceGenerator != null) {
			sentNonce = nonceGenerator.createNonce(db,
					TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis()));
		}
		return sentNonce;
	}

	private static String parseHeader(StringReader reader, String header)
			throws IOException {
		return parseHeader(reader.read(), header);
	}

	private static String parseHeader(String s, String header)
			throws IOException {
		if (s.isEmpty()) {
			throw new EOFException();
		}
		if (s.length() <= header.length()
				|| !s.startsWith(header)
				|| s.charAt(header.length()) != ' ') {
			throw new PackProtocolException(MessageFormat.format(
					JGitText.get().pushCertificateInvalidField, header));
		}
		return s.substring(header.length() + 1);
	}

	/**
	 * Receive a list of commands from the input encapsulated in a push
	 * certificate.
	 * <p>
	 * This method doesn't parse the first line {@code "push-cert \NUL
	 * &lt;capabilities&gt;"}, but assumes the first line including the
	 * capabilities has already been handled by the caller.
	 *
	 * @param pckIn
	 *            where we take the push certificate header from.
	 * @param stateless
	 *            affects nonce verification. When {@code stateless = true} the
	 *            {@code NonceGenerator} will allow for some time skew caused by
	 *            clients disconnected and reconnecting in the stateless smart
	 *            HTTP protocol.
	 * @throws java.io.IOException
	 *             if the certificate from the client is badly malformed or the
	 *             client disconnects before sending the entire certificate.
	 * @since 4.0
	 */
	public void receiveHeader(PacketLineIn pckIn, boolean stateless)
			throws IOException {
		receiveHeader(new PacketLineReader(pckIn), stateless);
	}

	private void receiveHeader(StringReader reader, boolean stateless)
			throws IOException {
		try {
			try {
				version = parseHeader(reader, VERSION);
			} catch (EOFException e) {
				return;
			}
			received = true;
			if (!version.equals(VERSION_0_1)) {
				throw new PackProtocolException(MessageFormat.format(
						JGitText.get().pushCertificateInvalidFieldValue, VERSION, version));
			}
			String rawPusher = parseHeader(reader, PUSHER);
			pusher = PushCertificateIdent.parse(rawPusher);
			if (pusher == null) {
				throw new PackProtocolException(MessageFormat.format(
						JGitText.get().pushCertificateInvalidFieldValue,
						PUSHER, rawPusher));
			}
			String next = reader.read();
			if (next.startsWith(PUSHEE)) {
				pushee = parseHeader(next, PUSHEE);
				receivedNonce = parseHeader(reader, NONCE);
			} else {
				receivedNonce = parseHeader(next, NONCE);
			}
			nonceStatus = nonceGenerator != null
					? nonceGenerator.verify(
						receivedNonce, sentNonce(), db, stateless, nonceSlopLimit)
					: NonceStatus.UNSOLICITED;
			// An empty line.
			if (!reader.read().isEmpty()) {
				throw new PackProtocolException(
						JGitText.get().pushCertificateInvalidHeader);
			}
		} catch (EOFException eof) {
			throw new PackProtocolException(
					JGitText.get().pushCertificateInvalidHeader, eof);
		}
	}

	/**
	 * Read the PGP signature.
	 * <p>
	 * This method assumes the line
	 * {@code "-----BEGIN PGP SIGNATURE-----"} has already been parsed,
	 * and continues parsing until an {@code "-----END PGP SIGNATURE-----"} is
	 * found, followed by {@code "push-cert-end"}.
	 *
	 * @param pckIn
	 *            where we read the signature from.
	 * @throws java.io.IOException
	 *             if the signature is invalid.
	 * @since 4.0
	 */
	public void receiveSignature(PacketLineIn pckIn) throws IOException {
		StringReader reader = new PacketLineReader(pckIn);
		receiveSignature(reader);
		if (!reader.read().equals(END_CERT)) {
			throw new PackProtocolException(
					JGitText.get().pushCertificateInvalidSignature);
		}
	}

	private void receiveSignature(StringReader reader) throws IOException {
		received = true;
		try {
			StringBuilder sig = new StringBuilder(BEGIN_SIGNATURE).append('\n');
			String line;
			while (!(line = reader.read()).equals(END_SIGNATURE)) {
				sig.append(line).append('\n');
			}
			signature = sig.append(END_SIGNATURE).append('\n').toString();
		} catch (EOFException eof) {
			throw new PackProtocolException(
					JGitText.get().pushCertificateInvalidSignature, eof);
		}
	}

	/**
	 * Add a command to the signature.
	 *
	 * @param cmd
	 *            the command.
	 * @since 4.1
	 */
	public void addCommand(ReceiveCommand cmd) {
		commands.add(cmd);
	}

	/**
	 * Add a command to the signature.
	 *
	 * @param line
	 *            the line read from the wire that produced this
	 *            command, with optional trailing newline already trimmed.
	 * @throws org.eclipse.jgit.errors.PackProtocolException
	 *             if the raw line cannot be parsed to a command.
	 * @since 4.0
	 */
	public void addCommand(String line) throws PackProtocolException {
		commands.add(parseCommand(line));
	}
}
