package com.stephensugden.guacamole.net.hmac;

import junit.framework.TestCase;
import org.glyptodon.guacamole.GuacamoleException;
import org.glyptodon.guacamole.net.auth.Credentials;
import org.glyptodon.guacamole.protocol.GuacamoleConfiguration;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;

import static com.stephensugden.guacamole.net.hmac.HmacAuthenticationProvider.*;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

public class HmacAuthenticationProviderTest extends TestCase {

    public void testSuccess() throws GuacamoleException {
        final String connectionId = "c/my-connection";

        HttpServletRequest request = mockRequest(new HashMap<String, String>() {{
            put(ID_PARAM,        connectionId);
            put("timestamp",     "1373563683000");
            put("guac.hostname", "10.2.3.4");
            put("guac.protocol", "rdp");
            put("guac.port",     "3389");
            // Test signature was generated with the following PHP snippet
            // base64_encode(hash_hmac('sha1', '1373563683000rdphostname10.2.3.4port3389', 'secret', true));
            put(SIGNATURE_PARAM, "6PHOr00TnhA10Ef9I4bLqeSXKYg=");
        }});

        Credentials credentials = new Credentials();
        credentials.setRequest(request);

        TimeProviderInterface timeProvider = mock(TimeProviderInterface.class);
        when(timeProvider.currentTimeMillis()).thenReturn(1373563683000L);
        HmacAuthenticationProvider authProvider = new HmacAuthenticationProvider(timeProvider);

        Map<String, GuacamoleConfiguration> configs = authProvider.getAuthorizedConfigurations(credentials);

        assertNotNull(configs);
        assertEquals(1, configs.size());
        GuacamoleConfiguration config = configs.get(connectionId.substring(2));
        assertNotNull(config);
        assertEquals("rdp", config.getProtocol());
    }

    private static HttpServletRequest mockRequest(final Map<String, String> queryParams) {
        HttpServletRequest request = mock(HttpServletRequest.class);

        when(request.getParameter(anyString())).then(new Answer<Object>() {
            @Override
            public String answer(InvocationOnMock invocationOnMock) throws Throwable {
                String key = (String) invocationOnMock.getArguments()[0];
                return queryParams.get(key);
            }
        });

        // Note this is invalidating the servlet API, but I only use the keys so I don't care
        when(request.getParameterMap()).thenReturn(queryParams);

        return request;
    }
}

@@ -2080,16 +2080,1245 @@
 %0A    %7D%0A%0A
+    public void testFailure() throws GuacamoleException %7B%0A        final String connectionId = %22c/my-connection%22;%0A        HttpServletRequest request = mockRequest(new HashMap%3CString, String%3E() %7B%7B%0A            put(ID_PARAM,        connectionId);%0A            put(%22timestamp%22,     %221373563683000%22);%0A            put(%22guac.hostname%22, %2210.2.3.5%22);  // changed hostname should invalidate signature%0A            put(%22guac.protocol%22, %22rdp%22);%0A            put(%22guac.port%22,     %223389%22);%0A            // Test signature was generated with the following PHP snippet%0A            // base64_encode(hash_hmac('sha1', '1373563683000rdphostname10.2.3.4port3389', 'secret', true));%0A            put(SIGNATURE_PARAM, %226PHOr00TnhA10Ef9I4bLqeSXKYg=%22);%0A        %7D%7D);%0A%0A        Credentials credentials = new Credentials();%0A        credentials.setRequest(request);%0A%0A        TimeProviderInterface timeProvider = mock(TimeProviderInterface.class);%0A        when(timeProvider.currentTimeMillis()).thenReturn(1373563683000L);%0A        HmacAuthenticationProvider authProvider = new HmacAuthenticationProvider(timeProvider);%0A%0A        Map%3CString, GuacamoleConfiguration%3E configs = authProvider.getAuthorizedConfigurations(credentials);%0A%0A        assertNull(configs);%0A    %7D%0A%0A
     priv

Add a test for authentication failure when the hostname changes.