/*
 * Copyright (C) 2018, Thomas Wolf <thomas.wolf@paranor.ch> and others
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Distribution License v. 1.0 which is available at
 * https://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */
package org.eclipse.jgit.internal.transport.sshd.proxy;

import static java.nio.charset.StandardCharsets.US_ASCII;
import static java.nio.charset.StandardCharsets.UTF_8;
import static java.text.MessageFormat.format;

import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
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(US_ASCII);
		Buffer buffer = new ByteArrayBuffer(data.length, false);
		buffer.putRawBytes(data);
		session.writeBuffer(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, 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(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);
		}

	}
}
