blob: 7a3af9d19d40e0587f2831474b58c319fe4ae27f [file] [log] [blame]
// 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.cloudstack.auth.test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.when;
import java.io.UnsupportedEncodingException;
import java.security.NoSuchAlgorithmException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import javax.naming.ConfigurationException;
import org.apache.cloudstack.auth.SHA256SaltedUserAuthenticator;
import org.bouncycastle.util.encoders.Base64;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import com.cloud.user.UserAccount;
import com.cloud.user.dao.UserAccountDao;
@RunWith(MockitoJUnitRunner.class)
public class AuthenticatorTest {
@Mock
UserAccount adminAccount;
@Mock
UserAccount adminAccount20Byte;
@Mock
UserAccountDao _userAccountDao;
@InjectMocks
SHA256SaltedUserAuthenticator authenticator;
@Before
public void setUp() throws Exception {
try {
authenticator.configure("SHA256", Collections.<String, Object> emptyMap());
} catch (ConfigurationException e) {
fail(e.toString());
}
when(_userAccountDao.getUserAccount("admin", 0L)).thenReturn(adminAccount);
when(_userAccountDao.getUserAccount("admin20Byte", 0L)).thenReturn(adminAccount20Byte);
when(_userAccountDao.getUserAccount("fake", 0L)).thenReturn(null);
//32 byte salt, and password="password"
when(adminAccount.getPassword()).thenReturn("WS3UHhBPKHZeV+G3jnn7G2N3luXgLSfL+2ORDieXa1U=:VhuFOrOU2IpsjKYH8cH1VDaDBh/VivjMcuADjeEbIig=");
//20 byte salt, and password="password"
when(adminAccount20Byte.getPassword()).thenReturn("QL2NsxVEmRuDaNRkvIyADny7C5w=:JoegiytiWnoBAxmSD/PwBZZYqkr746x2KzPrZNw4NgI=");
}
@Test
public void testEncode() throws UnsupportedEncodingException, NoSuchAlgorithmException {
String encodedPassword = authenticator.encode("password");
String storedPassword[] = encodedPassword.split(":");
assertEquals("hash must consist of two components", 2, storedPassword.length);
byte salt[] = Base64.decode(storedPassword[0]);
String hashedPassword = authenticator.encode("password", salt);
assertEquals("compare hashes", storedPassword[1], hashedPassword);
}
@Test
public void testAuthentication() throws UnsupportedEncodingException, NoSuchAlgorithmException {
Map<String, Object[]> dummyMap = new HashMap<String, Object[]>();
assertEquals("32 byte salt authenticated", true, authenticator.authenticate("admin", "password", 0L, dummyMap).first());
assertEquals("20 byte salt authenticated", true, authenticator.authenticate("admin20Byte", "password", 0L, dummyMap).first());
assertEquals("fake user not authenticated", false, authenticator.authenticate("fake", "fake", 0L, dummyMap).first());
assertEquals("bad password not authenticated", false, authenticator.authenticate("admin", "fake", 0L, dummyMap).first());
assertEquals("20 byte user bad password not authenticated", false, authenticator.authenticate("admin20Byte", "fake", 0L, dummyMap).first());
}
// @Test
// public void testTiming() throws UnsupportedEncodingException, NoSuchAlgorithmException {
// Map<String, Object[]> dummyMap = new HashMap<String, Object[]>();
// Double threshold = (double)500000; //half a millisecond
//
// Long t1 = System.nanoTime();
// authenticator.authenticate("admin", "password", 0L, dummyMap);
// Long t2 = System.nanoTime();
// authenticator.authenticate("admin20Byte", "password", 0L, dummyMap);
// Long t3 = System.nanoTime();
// authenticator.authenticate("fake", "fake", 0L, dummyMap);
// Long t4 = System.nanoTime();
// authenticator.authenticate("admin", "fake", 0L, dummyMap);
// Long t5 = System.nanoTime();
// Long diff1 = t2 - t1;
// Long diff2 = t3 - t2;
// Long diff3 = t4 - t3;
// Long diff4 = t5 - t4;
// Assert.assertTrue("All computation times within " + threshold / 1000000 + " milisecond",
// (diff1 <= threshold) && (diff2 <= threshold) && (diff3 <= threshold) && (diff4 <= threshold));
// }
}