/*
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
 */
package org.apache.qpid.systest.rest;

import static org.apache.qpid.server.security.auth.sasl.SaslUtil.generateCramMD5ClientResponse;
import static org.apache.qpid.server.security.auth.sasl.SaslUtil.generateCramMD5HashedClientResponse;
import static org.apache.qpid.server.security.auth.sasl.SaslUtil.generateCramMD5HexClientResponse;
import static org.apache.qpid.server.security.auth.sasl.SaslUtil.generatePlainClientResponse;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletResponse;
import javax.xml.bind.DatatypeConverter;

import org.apache.qpid.server.model.AuthenticationProvider;
import org.apache.qpid.server.security.auth.manager.Base64MD5PasswordDatabaseAuthenticationManager;
import org.apache.qpid.test.utils.TestBrokerConfiguration;

public class SaslRestTest extends QpidRestTestCase
{
    @Override
    public void startDefaultBroker()
    {
        // prevent broker from starting in setUp
    }

    public void startBrokerNow() throws Exception
    {
        super.startDefaultBroker();
        getRestTestHelper().setUsernameAndPassword(null,null);
    }

    public void testGetMechanismsWithBrokerPlainPasswordPrincipalDatabase() throws Exception
    {
        startBrokerNow();

        Map<String, Object> saslData = getRestTestHelper().getJsonAsMap("/service/sasl");
        assertNotNull("mechanisms attribute is not found", saslData.get("mechanisms"));

        @SuppressWarnings("unchecked")
        List<String> mechanisms = (List<String>) saslData.get("mechanisms");
        String[] expectedMechanisms = { "CRAM-MD5" };
        for (String mechanism : expectedMechanisms)
        {
            assertTrue("Mechanism " + mechanism + " is not found", mechanisms.contains(mechanism));
        }
        assertNull("Unexpected user was returned: " + saslData.get("user"), saslData.get("user"));
    }

    public void testGetMechanismsWithBrokerBase64MD5FilePrincipalDatabase() throws Exception
    {
        configureBase64MD5FilePrincipalDatabase();
        startBrokerNow();

        Map<String, Object> saslData = getRestTestHelper().getJsonAsMap("/service/sasl");
        assertNotNull("mechanisms attribute is not found", saslData.get("mechanisms"));

        @SuppressWarnings("unchecked")
        List<String> mechanisms = (List<String>) saslData.get("mechanisms");
        String[] expectedMechanisms = { "CRAM-MD5-HEX", "CRAM-MD5-HASHED" };
        for (String mechanism : expectedMechanisms)
        {
            assertTrue("Mechanism " + mechanism + " is not found", mechanisms.contains(mechanism));
        }

        assertNull("Unexpected user was returned: " + saslData.get("user"), saslData.get("user"));
    }

    public void testPlainSaslAuthenticationForValidCredentials() throws Exception
    {
        startBrokerNow();

        byte[] responseBytes = generatePlainClientResponse("admin", "admin");
        String responseData = DatatypeConverter.printBase64Binary(responseBytes);
        String parameters= "mechanism=PLAIN&response=" + responseData;

        HttpURLConnection connection = getRestTestHelper().openManagementConnection("/service/sasl", "POST");
        OutputStream os = connection.getOutputStream();
        os.write(parameters.getBytes());
        os.flush();

        int code = getRestTestHelper().submitRequest("/service/sasl", "POST", parameters.getBytes());
        assertEquals("Unexpected response code", 200, code);

        List<String> cookies = connection.getHeaderFields().get("Set-Cookie");

        // request authenticated user details
        connection = getRestTestHelper().openManagementConnection("/service/sasl", "GET");
        applyCookiesToConnection(cookies, connection);
        Map<String, Object> response2 = getRestTestHelper().readJsonResponseAsMap(connection);
        assertEquals("Unexpected user", "admin", response2.get("user"));
    }

    public void testPlainSaslAuthenticationForIncorrectPassword() throws Exception
    {
        startBrokerNow();

        byte[] responseBytes = generatePlainClientResponse("admin", "incorrect");
        String responseData = DatatypeConverter.printBase64Binary(responseBytes);
        String parameters= "mechanism=PLAIN&response=" + responseData;

        HttpURLConnection connection = getRestTestHelper().openManagementConnection("/service/sasl", "POST");
        OutputStream os = connection.getOutputStream();
        os.write(parameters.getBytes());
        os.flush();

        int code = connection.getResponseCode();
        assertEquals("Unexpected response code", 401, code);

        List<String> cookies = connection.getHeaderFields().get("Set-Cookie");

        // request authenticated user details
        connection = getRestTestHelper().openManagementConnection("/service/sasl", "GET");
        applyCookiesToConnection(cookies, connection);
        Map<String, Object> response2 = getRestTestHelper().readJsonResponseAsMap(connection);
        assertNull("Unexpected user", response2.get("user"));
    }

    public void testPlainSaslAuthenticationForNonExistingUser() throws Exception
    {
        startBrokerNow();

        byte[] responseBytes = generatePlainClientResponse("nonexisting", "admin");
        String responseData = DatatypeConverter.printBase64Binary(responseBytes);
        String parameters= "mechanism=PLAIN&response=" + responseData;

        HttpURLConnection connection = getRestTestHelper().openManagementConnection("/service/sasl", "POST");
        OutputStream os = connection.getOutputStream();
        os.write(parameters.getBytes());
        os.flush();

        int code = connection.getResponseCode();
        assertEquals("Unexpected response code", 401, code);

        List<String> cookies = connection.getHeaderFields().get("Set-Cookie");

        // request authenticated user details
        connection = getRestTestHelper().openManagementConnection("/service/sasl", "GET");
        applyCookiesToConnection(cookies, connection);
        Map<String, Object> response2 = getRestTestHelper().readJsonResponseAsMap(connection);
        assertNull("Unexpected user", response2.get("user"));
    }

    public void testCramMD5SaslAuthenticationForValidCredentials() throws Exception
    {
        startBrokerNow();

        // request the challenge for CRAM-MD5
        HttpURLConnection connection = requestSasServerChallenge("CRAM-MD5");
        List<String> cookies = connection.getHeaderFields().get("Set-Cookie");

        // authenticate user with correct credentials
        int code = authenticateUser(connection, "admin", "admin", "CRAM-MD5");
        assertEquals("Unexpected response code", 200, code);

        // request authenticated user details
        connection = getRestTestHelper().openManagementConnection("/service/sasl", "GET");
        applyCookiesToConnection(cookies, connection);
        Map<String, Object> response2 = getRestTestHelper().readJsonResponseAsMap(connection);
        assertEquals("Unexpected user", "admin", response2.get("user"));
    }

    public void testCramMD5SaslAuthenticationForIncorrectPassword() throws Exception
    {
        startBrokerNow();

        // request the challenge for CRAM-MD5
        HttpURLConnection connection = requestSasServerChallenge("CRAM-MD5");
        List<String> cookies = connection.getHeaderFields().get("Set-Cookie");

        // authenticate user with correct credentials
        int code = authenticateUser(connection, "admin", "incorrect", "CRAM-MD5");
        assertEquals("Unexpected response code", 401, code);

        // request authenticated user details
        connection = getRestTestHelper().openManagementConnection("/service/sasl", "GET");
        applyCookiesToConnection(cookies, connection);
        Map<String, Object> response2 = getRestTestHelper().readJsonResponseAsMap(connection);
        assertNull("Unexpected user", response2.get("user"));
    }

    public void testCramMD5SaslAuthenticationForNonExistingUser() throws Exception
    {
        startBrokerNow();

        // request the challenge for CRAM-MD5
        HttpURLConnection connection = requestSasServerChallenge("CRAM-MD5");
        List<String> cookies = connection.getHeaderFields().get("Set-Cookie");

        // authenticate user with correct credentials
        int code = authenticateUser(connection, "nonexisting", "admin", "CRAM-MD5");
        assertEquals("Unexpected response code", 401, code);

        // request authenticated user details
        connection = getRestTestHelper().openManagementConnection("/service/sasl", "GET");
        applyCookiesToConnection(cookies, connection);
        Map<String, Object> response2 = getRestTestHelper().readJsonResponseAsMap(connection);
        assertNull("Unexpected user",  response2.get("user"));
    }

    public void testCramMD5HexSaslAuthenticationForValidCredentials() throws Exception
    {
        configureBase64MD5FilePrincipalDatabase();
        startBrokerNow();

        // request the challenge for CRAM-MD5-HEX
        HttpURLConnection connection = requestSasServerChallenge("CRAM-MD5-HEX");
        List<String> cookies = connection.getHeaderFields().get("Set-Cookie");

        // authenticate user with correct credentials
        int code = authenticateUser(connection, "admin", "admin", "CRAM-MD5-HEX");
        assertEquals("Unexpected response code", 200, code);

        // request authenticated user details
        connection = getRestTestHelper().openManagementConnection("/service/sasl", "GET");
        applyCookiesToConnection(cookies, connection);
        Map<String, Object> response2 = getRestTestHelper().readJsonResponseAsMap(connection);
        assertEquals("Unexpected user", "admin", response2.get("user"));
    }

    public void testCramMD5HexSaslAuthenticationForIncorrectPassword() throws Exception
    {
        configureBase64MD5FilePrincipalDatabase();
        startBrokerNow();

        HttpURLConnection connection = requestSasServerChallenge("CRAM-MD5-HEX");
        List<String> cookies = connection.getHeaderFields().get("Set-Cookie");

        // try to authenticate user with incorrect passowrd
        int code = authenticateUser(connection, "admin", "incorrect", "CRAM-MD5-HEX");
        assertEquals("Unexpected response code", 401, code);

        // request authenticated user details
        connection = getRestTestHelper().openManagementConnection("/service/sasl", "GET");
        applyCookiesToConnection(cookies, connection);
        Map<String, Object> response2 = getRestTestHelper().readJsonResponseAsMap(connection);
        assertNull("Unexpected user", response2.get("user"));
    }

    public void testCramMD5HexSaslAuthenticationForNonExistingUser() throws Exception
    {
        configureBase64MD5FilePrincipalDatabase();
        startBrokerNow();

        HttpURLConnection connection = requestSasServerChallenge("CRAM-MD5-HEX");
        List<String> cookies = connection.getHeaderFields().get("Set-Cookie");

        // try to authenticate non-existing user
        int code = authenticateUser(connection, "nonexisting", "admin", "CRAM-MD5-HEX");
        assertEquals("Unexpected response code", 401, code);

        // request authenticated user details
        connection = getRestTestHelper().openManagementConnection("/service/sasl", "GET");
        applyCookiesToConnection(cookies, connection);
        Map<String, Object> response2 = getRestTestHelper().readJsonResponseAsMap(connection);
        assertNull("Unexpected user", response2.get("user"));
    }

    public void testRequestingAuthenticationForUnsupportedSaslMechanism() throws Exception
    {
        startBrokerNow();
        HttpURLConnection connection = requestSasServerChallenge("UNSUPPORTED");
        int responseCode = connection.getResponseCode();
        connection.disconnect();
        assertEquals("Unexpected response", HttpServletResponse.SC_EXPECTATION_FAILED, responseCode);
    }

    public void testCramMD5HashedSaslAuthenticationForValidCredentials() throws Exception
    {
        configureBase64MD5FilePrincipalDatabase();
        startBrokerNow();

        // request the challenge for CRAM-MD5-HASHED
        HttpURLConnection connection = requestSasServerChallenge("CRAM-MD5-HASHED");
        List<String> cookies = connection.getHeaderFields().get("Set-Cookie");

        // authenticate user with correct credentials
        int code = authenticateUser(connection, "admin", "admin", "CRAM-MD5-HASHED");
        assertEquals("Unexpected response code", 200, code);

        // request authenticated user details
        connection = getRestTestHelper().openManagementConnection("/service/sasl", "GET");
        applyCookiesToConnection(cookies, connection);
        Map<String, Object> response2 = getRestTestHelper().readJsonResponseAsMap(connection);
        assertEquals("Unexpected user", "admin", response2.get("user"));
    }

    public void testCramMD5HashedSaslAuthenticationForInvalidPassword() throws Exception
    {
        configureBase64MD5FilePrincipalDatabase();
        startBrokerNow();

        HttpURLConnection connection = requestSasServerChallenge("CRAM-MD5-HASHED");
        List<String> cookies = connection.getHeaderFields().get("Set-Cookie");

        // try to authenticate user with incorrect passowrd
        int code = authenticateUser(connection, "admin", "incorrect", "CRAM-MD5-HASHED");
        assertEquals("Unexpected response code", 401, code);

        // request authenticated user details
        connection = getRestTestHelper().openManagementConnection("/service/sasl", "GET");
        applyCookiesToConnection(cookies, connection);
        Map<String, Object> response2 = getRestTestHelper().readJsonResponseAsMap(connection);
        assertNull("Unexpected user", response2.get("user"));
    }

    private HttpURLConnection requestSasServerChallenge(String mechanism) throws IOException
    {
        HttpURLConnection connection = getRestTestHelper().openManagementConnection("/service/sasl", "POST");
        OutputStream os = connection.getOutputStream();
        os.write(("mechanism=" + mechanism).getBytes());
        os.flush();
        return connection;
    }

    public int authenticateUser(HttpURLConnection requestChallengeConnection, String userName, String userPassword, String mechanism)
            throws Exception
    {
        // get the response
        Map<String, Object> response = getRestTestHelper().readJsonResponseAsMap(requestChallengeConnection);
        String challenge = (String) response.get("challenge");
        assertNotNull("Challenge is not found", challenge);

        // preserve cookies to have the same server session
        List<String> cookies = requestChallengeConnection.getHeaderFields().get("Set-Cookie");

        // generate the authentication response for the challenge received
        byte[] challengeBytes = DatatypeConverter.parseBase64Binary(challenge);
        byte[] responseBytes = generateClientResponse(mechanism, userName, userPassword, challengeBytes);
        String responseData = DatatypeConverter.printBase64Binary(responseBytes);
        String requestParameters = ("id=" + response.get("id") + "&response=" + responseData);

        // re-open connection
        HttpURLConnection authenticateConnection = getRestTestHelper().openManagementConnection("/service/sasl", "POST");

        // set cookies to use the same server session
        applyCookiesToConnection(cookies, authenticateConnection);
        OutputStream os = authenticateConnection.getOutputStream();
        os.write(requestParameters.getBytes());
        os.flush();
        return authenticateConnection.getResponseCode();
    }

    private byte[] generateClientResponse(String mechanism, String userName, String userPassword, byte[] challengeBytes) throws Exception
    {
        byte[] responseBytes =  null;
        if ("CRAM-MD5-HEX".equalsIgnoreCase(mechanism))
        {
            responseBytes = generateCramMD5HexClientResponse(userName, userPassword, challengeBytes);
        }
        else if ("CRAM-MD5".equalsIgnoreCase(mechanism))
        {
            responseBytes = generateCramMD5ClientResponse(userName, userPassword, challengeBytes);
        }
        else if ("CRAM-MD5-HASHED".equalsIgnoreCase(mechanism))
        {
            responseBytes = generateCramMD5HashedClientResponse(userName, userPassword, challengeBytes);
        }
        else
        {
            throw new RuntimeException("Not implemented test mechanism " + mechanism);
        }
        return responseBytes;
    }

    private void applyCookiesToConnection(List<String> cookies, HttpURLConnection connection)
    {
        for (String cookie : cookies)
        {
            connection.addRequestProperty("Cookie", cookie.split(";", 2)[0]);
        }
    }

    private void configureBase64MD5FilePrincipalDatabase() throws IOException
    {
        // generate user password entry
        String passwordFileEntry;
        try
        {

            MessageDigest md = MessageDigest.getInstance("MD5");

            md.update("admin".getBytes("utf-8"));

            passwordFileEntry = "admin" + ":" + DatatypeConverter.printBase64Binary(md.digest());
        }
        catch (NoSuchAlgorithmException e)
        {
            throw new RuntimeException(e);
        }

        // store the entry in the file
        File passwordFile = File.createTempFile("passwd", "pwd");
        passwordFile.deleteOnExit();

        FileWriter writer = null;
        try
        {
            writer = new FileWriter(passwordFile);
            writer.write(passwordFileEntry);
        }
        finally
        {
            writer.close();
        }

        // configure broker to use Base64MD5PasswordFilePrincipalDatabase
        Map<String, Object> newAttributes = new HashMap<String, Object>();
        newAttributes.put("path", passwordFile.getAbsolutePath());
        newAttributes.put(AuthenticationProvider.TYPE, Base64MD5PasswordDatabaseAuthenticationManager.PROVIDER_TYPE);
        getDefaultBrokerConfiguration().setObjectAttributes(AuthenticationProvider.class, TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER, newAttributes);
    }
}
