/*
 * Copyright (C) 2018, Thomas Wolf <thomas.wolf@paranor.ch>
 * 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.internal.transport.sshd.proxy;

import static java.text.MessageFormat.format;

import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

import org.apache.sshd.client.session.ClientSession;
import org.apache.sshd.common.io.IoSession;
import org.apache.sshd.common.util.Readable;
import org.apache.sshd.common.util.buffer.Buffer;
import org.apache.sshd.common.util.buffer.ByteArrayBuffer;
import org.eclipse.jgit.annotations.NonNull;
import org.eclipse.jgit.internal.transport.sshd.GssApiMechanisms;
import org.eclipse.jgit.internal.transport.sshd.SshdText;
import org.eclipse.jgit.internal.transport.sshd.auth.AuthenticationHandler;
import org.eclipse.jgit.internal.transport.sshd.auth.BasicAuthentication;
import org.eclipse.jgit.internal.transport.sshd.auth.GssApiAuthentication;
import org.eclipse.jgit.util.Base64;
import org.ietf.jgss.GSSContext;

/**
 * Simple HTTP proxy connector using Basic Authentication.
 */
public class HttpClientConnector extends AbstractClientProxyConnector {

	private static final String HTTP_HEADER_PROXY_AUTHENTICATION = "Proxy-Authentication:"; //$NON-NLS-1$

	private static final String HTTP_HEADER_PROXY_AUTHORIZATION = "Proxy-Authorization:"; //$NON-NLS-1$

	private HttpAuthenticationHandler basic;

	private HttpAuthenticationHandler negotiate;

	private List<HttpAuthenticationHandler> availableAuthentications;

	private Iterator<HttpAuthenticationHandler> clientAuthentications;

	private HttpAuthenticationHandler authenticator;

	private boolean ongoing;

	/**
	 * Creates a new {@link HttpClientConnector}. The connector supports
	 * anonymous proxy connections as well as Basic and Negotiate
	 * authentication.
	 *
	 * @param proxyAddress
	 *            of the proxy server we're connecting to
	 * @param remoteAddress
	 *            of the target server to connect to
	 */
	public HttpClientConnector(@NonNull InetSocketAddress proxyAddress,
			@NonNull InetSocketAddress remoteAddress) {
		this(proxyAddress, remoteAddress, null, null);
	}

	/**
	 * Creates a new {@link HttpClientConnector}. The connector supports
	 * anonymous proxy connections as well as Basic and Negotiate
	 * authentication. If a user name and password are given, the connector
	 * tries pre-emptive Basic authentication.
	 *
	 * @param proxyAddress
	 *            of the proxy server we're connecting to
	 * @param remoteAddress
	 *            of the target server to connect to
	 * @param proxyUser
	 *            to authenticate at the proxy with
	 * @param proxyPassword
	 *            to authenticate at the proxy with
	 */
	public HttpClientConnector(@NonNull InetSocketAddress proxyAddress,
			@NonNull InetSocketAddress remoteAddress, String proxyUser,
			char[] proxyPassword) {
		super(proxyAddress, remoteAddress, proxyUser, proxyPassword);
		basic = new HttpBasicAuthentication();
		negotiate = new NegotiateAuthentication();
		availableAuthentications = new ArrayList<>(2);
		availableAuthentications.add(negotiate);
		availableAuthentications.add(basic);
		clientAuthentications = availableAuthentications.iterator();
	}

	private void close() {
		HttpAuthenticationHandler current = authenticator;
		authenticator = null;
		if (current != null) {
			current.close();
		}
	}

	@Override
	public void sendClientProxyMetadata(ClientSession sshSession)
			throws Exception {
		init(sshSession);
		IoSession session = sshSession.getIoSession();
		session.addCloseFutureListener(f -> close());
		StringBuilder msg = connect();
		if (proxyUser != null && !proxyUser.isEmpty()
				|| proxyPassword != null && proxyPassword.length > 0) {
			authenticator = basic;
			basic.setParams(null);
			basic.start();
			msg = authenticate(msg, basic.getToken());
			clearPassword();
			proxyUser = null;
		}
		ongoing = true;
		try {
			send(msg, session);
		} catch (Exception e) {
			ongoing = false;
			throw e;
		}
	}

	private void send(StringBuilder msg, IoSession session) throws Exception {
		byte[] data = eol(msg).toString().getBytes(StandardCharsets.US_ASCII);
		Buffer buffer = new ByteArrayBuffer(data.length, false);
		buffer.putRawBytes(data);
		session.writePacket(buffer).verify(getTimeout());
	}

	private StringBuilder connect() {
		StringBuilder msg = new StringBuilder();
		// Persistent connections are the default in HTTP 1.1 (see RFC 2616),
		// but let's be explicit.
		return msg.append(format(
				"CONNECT {0}:{1} HTTP/1.1\r\nProxy-Connection: keep-alive\r\nConnection: keep-alive\r\nHost: {0}:{1}\r\n", //$NON-NLS-1$
				remoteAddress.getHostString(),
				Integer.toString(remoteAddress.getPort())));
	}

	private StringBuilder authenticate(StringBuilder msg, String token) {
		msg.append(HTTP_HEADER_PROXY_AUTHORIZATION).append(' ').append(token);
		return eol(msg);
	}

	private StringBuilder eol(StringBuilder msg) {
		return msg.append('\r').append('\n');
	}

	@Override
	public void messageReceived(IoSession session, Readable buffer)
			throws Exception {
		try {
			int length = buffer.available();
			byte[] data = new byte[length];
			buffer.getRawBytes(data, 0, length);
			String[] reply = new String(data, StandardCharsets.US_ASCII)
					.split("\r\n"); //$NON-NLS-1$
			handleMessage(session, Arrays.asList(reply));
		} catch (Exception e) {
			if (authenticator != null) {
				authenticator.close();
				authenticator = null;
			}
			ongoing = false;
			try {
				setDone(false);
			} catch (Exception inner) {
				e.addSuppressed(inner);
			}
			throw e;
		}
	}

	private void handleMessage(IoSession session, List<String> reply)
			throws Exception {
		if (reply.isEmpty() || reply.get(0).isEmpty()) {
			throw new IOException(
					format(SshdText.get().proxyHttpUnexpectedReply,
							proxyAddress, "<empty>")); //$NON-NLS-1$
		}
		try {
			StatusLine status = HttpParser.parseStatusLine(reply.get(0));
			if (!ongoing) {
				throw new IOException(format(
						SshdText.get().proxyHttpUnexpectedReply, proxyAddress,
						Integer.toString(status.getResultCode()),
						status.getReason()));
			}
			switch (status.getResultCode()) {
			case HttpURLConnection.HTTP_OK:
				if (authenticator != null) {
					authenticator.close();
				}
				authenticator = null;
				ongoing = false;
				setDone(true);
				break;
			case HttpURLConnection.HTTP_PROXY_AUTH:
				List<AuthenticationChallenge> challenges = HttpParser
						.getAuthenticationHeaders(reply,
								HTTP_HEADER_PROXY_AUTHENTICATION);
				authenticator = selectProtocol(challenges, authenticator);
				if (authenticator == null) {
					throw new IOException(
							format(SshdText.get().proxyCannotAuthenticate,
									proxyAddress));
				}
				String token = authenticator.getToken();
				if (token == null) {
					throw new IOException(
							format(SshdText.get().proxyCannotAuthenticate,
									proxyAddress));
				}
				send(authenticate(connect(), token), session);
				break;
			default:
				throw new IOException(format(SshdText.get().proxyHttpFailure,
						proxyAddress, Integer.toString(status.getResultCode()),
						status.getReason()));
			}
		} catch (HttpParser.ParseException e) {
			throw new IOException(
					format(SshdText.get().proxyHttpUnexpectedReply,
					proxyAddress, reply.get(0)));
		}
	}

	private HttpAuthenticationHandler selectProtocol(
			List<AuthenticationChallenge> challenges,
			HttpAuthenticationHandler current) throws Exception {
		if (current != null && !current.isDone()) {
			AuthenticationChallenge challenge = getByName(challenges,
					current.getName());
			if (challenge != null) {
				current.setParams(challenge);
				current.process();
				return current;
			}
		}
		if (current != null) {
			current.close();
		}
		while (clientAuthentications.hasNext()) {
			HttpAuthenticationHandler next = clientAuthentications.next();
			if (!next.isDone()) {
				AuthenticationChallenge challenge = getByName(challenges,
						next.getName());
				if (challenge != null) {
					next.setParams(challenge);
					next.start();
					return next;
				}
			}
		}
		return null;
	}

	private AuthenticationChallenge getByName(
			List<AuthenticationChallenge> challenges,
			String name) {
		return challenges.stream()
				.filter(c -> c.getMechanism().equalsIgnoreCase(name))
				.findFirst().orElse(null);
	}

	private interface HttpAuthenticationHandler
			extends AuthenticationHandler<AuthenticationChallenge, String> {

		public String getName();
	}

	/**
	 * @see <a href="https://tools.ietf.org/html/rfc7617">RFC 7617</a>
	 */
	private class HttpBasicAuthentication
			extends BasicAuthentication<AuthenticationChallenge, String>
			implements HttpAuthenticationHandler {

		private boolean asked;

		public HttpBasicAuthentication() {
			super(proxyAddress, proxyUser, proxyPassword);
		}

		@Override
		public String getName() {
			return "Basic"; //$NON-NLS-1$
		}

		@Override
		protected void askCredentials() {
			// We ask only once.
			if (asked) {
				throw new IllegalStateException(
						"Basic auth: already asked user for password"); //$NON-NLS-1$
			}
			asked = true;
			super.askCredentials();
			done = true;
		}

		@Override
		public String getToken() throws Exception {
			if (user.indexOf(':') >= 0) {
				throw new IOException(format(
						SshdText.get().proxyHttpInvalidUserName, proxy, user));
			}
			byte[] rawUser = user.getBytes(StandardCharsets.UTF_8);
			byte[] toEncode = new byte[rawUser.length + 1 + password.length];
			System.arraycopy(rawUser, 0, toEncode, 0, rawUser.length);
			toEncode[rawUser.length] = ':';
			System.arraycopy(password, 0, toEncode, rawUser.length + 1,
					password.length);
			Arrays.fill(password, (byte) 0);
			String result = Base64.encodeBytes(toEncode);
			Arrays.fill(toEncode, (byte) 0);
			return getName() + ' ' + result;
		}

	}

	/**
	 * @see <a href="https://tools.ietf.org/html/rfc4559">RFC 4559</a>
	 */
	private class NegotiateAuthentication
			extends GssApiAuthentication<AuthenticationChallenge, String>
			implements HttpAuthenticationHandler {

		public NegotiateAuthentication() {
			super(proxyAddress);
		}

		@Override
		public String getName() {
			return "Negotiate"; //$NON-NLS-1$
		}

		@Override
		public String getToken() throws Exception {
			return getName() + ' ' + Base64.encodeBytes(token);
		}

		@Override
		protected GSSContext createContext() throws Exception {
			return GssApiMechanisms.createContext(GssApiMechanisms.SPNEGO,
					GssApiMechanisms.getCanonicalName(proxyAddress));
		}

		@Override
		protected byte[] extractToken(AuthenticationChallenge input)
				throws Exception {
			String received = input.getToken();
			if (received == null) {
				return new byte[0];
			}
			return Base64.decode(received);
		}

	}
}
