| New file |
| | |
| | | /* |
| | | * CDDL HEADER START |
| | | * |
| | | * The contents of this file are subject to the terms of the |
| | | * Common Development and Distribution License, Version 1.0 only |
| | | * (the "License"). You may not use this file except in compliance |
| | | * with the License. |
| | | * |
| | | * You can obtain a copy of the license at |
| | | * trunk/opends/resource/legal-notices/OpenDS.LICENSE |
| | | * or https://OpenDS.dev.java.net/OpenDS.LICENSE. |
| | | * See the License for the specific language governing permissions |
| | | * and limitations under the License. |
| | | * |
| | | * When distributing Covered Code, include this CDDL HEADER in each |
| | | * file and include the License file at |
| | | * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable, |
| | | * add the following below this CDDL HEADER, with the fields enclosed |
| | | * by brackets "[]" replaced with your own identifying information: |
| | | * Portions Copyright [yyyy] [name of copyright owner] |
| | | * |
| | | * CDDL HEADER END |
| | | * |
| | | * |
| | | * Copyright 2011 ForgeRock AS. |
| | | */ |
| | | package org.opends.server.api; |
| | | |
| | | |
| | | |
| | | import static org.testng.Assert.assertEquals; |
| | | import static org.testng.Assert.assertFalse; |
| | | import static org.testng.Assert.assertTrue; |
| | | |
| | | import org.opends.server.TestCaseUtils; |
| | | import org.opends.server.core.BindOperation; |
| | | import org.opends.server.core.DirectoryServer; |
| | | import org.opends.server.protocols.internal.InternalClientConnection; |
| | | import org.opends.server.types.*; |
| | | import org.testng.annotations.BeforeClass; |
| | | import org.testng.annotations.Test; |
| | | |
| | | |
| | | |
| | | /** |
| | | * Test authentication policy interaction. |
| | | */ |
| | | public class AuthenticationPolicyTestCase extends APITestCase |
| | | { |
| | | |
| | | /** |
| | | * A mock policy which records which methods have been called and their |
| | | * parameters. |
| | | */ |
| | | private final class MockPolicy extends AuthenticationPolicy |
| | | { |
| | | private boolean isPolicyFinalized = false; |
| | | |
| | | private boolean isStateFinalized = false; |
| | | |
| | | private final boolean matches; |
| | | |
| | | private ByteString matchedPassword = null; |
| | | |
| | | |
| | | |
| | | /** |
| | | * Returns {@code true} if {@code finalizeAuthenticationPolicy} was called. |
| | | * |
| | | * @return {@code true} if {@code finalizeAuthenticationPolicy} was called. |
| | | */ |
| | | public boolean isPolicyFinalized() |
| | | { |
| | | return isPolicyFinalized; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Returns {@code true} if {@code finalizeStateAfterBind} was called. |
| | | * |
| | | * @return {@code true} if {@code finalizeStateAfterBind} was called. |
| | | */ |
| | | public boolean isStateFinalized() |
| | | { |
| | | return isStateFinalized; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Returns the password which was tested. |
| | | * |
| | | * @return The password which was tested. |
| | | */ |
| | | public String getMatchedPassword() |
| | | { |
| | | return matchedPassword.toString(); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Creates a new mock policy. |
| | | * |
| | | * @param matches |
| | | * The result to always return from {@code passwordMatches}. |
| | | */ |
| | | public MockPolicy(boolean matches) |
| | | { |
| | | this.matches = matches; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public DN getDN() |
| | | { |
| | | return policyDN; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public AuthenticationPolicyState createAuthenticationPolicyState( |
| | | Entry userEntry, long time) throws DirectoryException |
| | | { |
| | | return new AuthenticationPolicyState() |
| | | { |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public boolean passwordMatches(ByteString password) |
| | | throws DirectoryException |
| | | { |
| | | matchedPassword = password; |
| | | return matches; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public void finalizeStateAfterBind() throws DirectoryException |
| | | { |
| | | isStateFinalized = true; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public AuthenticationPolicy getAuthenticationPolicy() |
| | | { |
| | | return MockPolicy.this; |
| | | } |
| | | }; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public void finalizeAuthenticationPolicy() |
| | | { |
| | | isPolicyFinalized = true; |
| | | } |
| | | |
| | | } |
| | | |
| | | |
| | | |
| | | private final String policyDNString = "cn=test policy,o=test"; |
| | | private final String userDNString = "cn=test user,o=test"; |
| | | private DN policyDN; |
| | | |
| | | |
| | | |
| | | /** |
| | | * Ensures that the Directory Server is running and creates a test backend |
| | | * containing a single test user. |
| | | * |
| | | * @throws Exception |
| | | * If an unexpected problem occurs. |
| | | */ |
| | | @BeforeClass() |
| | | public void beforeClass() throws Exception |
| | | { |
| | | TestCaseUtils.startServer(); |
| | | |
| | | policyDN = DN.decode(policyDNString); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Test simple authentication where password validation succeeds. |
| | | * |
| | | * @throws Exception |
| | | * If an unexpected exception occurred. |
| | | */ |
| | | @Test |
| | | public void testSimpleBindAllowed() throws Exception |
| | | { |
| | | testSimpleBind(true); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Test simple authentication where password validation fails. |
| | | * |
| | | * @throws Exception |
| | | * If an unexpected exception occurred. |
| | | */ |
| | | @Test |
| | | public void testSimpleBindRefused() throws Exception |
| | | { |
| | | testSimpleBind(false); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Test simple authentication where password validation succeeds. |
| | | * |
| | | * @throws Exception |
| | | * If an unexpected exception occurred. |
| | | */ |
| | | @Test |
| | | public void testSASLPLAINBindAllowed() throws Exception |
| | | { |
| | | testSASLPLAINBind(true); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Test simple authentication where password validation fails. |
| | | * |
| | | * @throws Exception |
| | | * If an unexpected exception occurred. |
| | | */ |
| | | @Test |
| | | public void testSASLPLAINBindRefused() throws Exception |
| | | { |
| | | testSASLPLAINBind(false); |
| | | } |
| | | |
| | | |
| | | |
| | | private void testSimpleBind(boolean allow) throws Exception |
| | | { |
| | | MockPolicy policy = new MockPolicy(allow); |
| | | DirectoryServer.registerAuthenticationPolicy(policyDN, policy); |
| | | try |
| | | { |
| | | // Create an empty test backend 'o=test' |
| | | TestCaseUtils.initializeTestBackend(true); |
| | | |
| | | /* |
| | | * The test user which who will be authenticated. |
| | | */ |
| | | TestCaseUtils.addEntries( |
| | | /* @formatter:off */ |
| | | "dn: " + userDNString, |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "ds-pwp-password-policy-dn: " + policyDNString, |
| | | "userPassword: password", |
| | | "sn: user", |
| | | "cn: test user" |
| | | /* @formatter:on */ |
| | | ); |
| | | |
| | | // Perform the simple bind. |
| | | InternalClientConnection conn = InternalClientConnection |
| | | .getRootConnection(); |
| | | BindOperation bind = conn.processSimpleBind(userDNString, "password"); |
| | | |
| | | // Check authentication result. |
| | | assertEquals(bind.getResultCode(), allow ? ResultCode.SUCCESS |
| | | : ResultCode.INVALID_CREDENTIALS); |
| | | |
| | | // Verify interaction with the policy/state. |
| | | assertTrue(policy.isStateFinalized()); |
| | | assertFalse(policy.isPolicyFinalized()); |
| | | assertEquals(policy.getMatchedPassword(), "password"); |
| | | } |
| | | finally |
| | | { |
| | | DirectoryServer.deregisterAuthenticationPolicy(policyDN); |
| | | assertTrue(policy.isPolicyFinalized()); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | private void testSASLPLAINBind(boolean allow) throws Exception |
| | | { |
| | | MockPolicy policy = new MockPolicy(allow); |
| | | DirectoryServer.registerAuthenticationPolicy(policyDN, policy); |
| | | try |
| | | { |
| | | // Create an empty test backend 'o=test' |
| | | TestCaseUtils.initializeTestBackend(true); |
| | | |
| | | /* |
| | | * The test user which who will be authenticated. |
| | | */ |
| | | TestCaseUtils.addEntries( |
| | | /* @formatter:off */ |
| | | "dn: " + userDNString, |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "ds-pwp-password-policy-dn: " + policyDNString, |
| | | "userPassword: password", |
| | | "sn: user", |
| | | "cn: test user" |
| | | /* @formatter:on */ |
| | | ); |
| | | |
| | | // Perform the simple bind. |
| | | InternalClientConnection conn = InternalClientConnection |
| | | .getRootConnection(); |
| | | |
| | | ByteStringBuilder credentials = new ByteStringBuilder(); |
| | | credentials.append((byte) 0); |
| | | credentials.append("dn:" + userDNString); |
| | | credentials.append((byte) 0); |
| | | credentials.append("password"); |
| | | |
| | | BindOperation bind = conn.processSASLBind(DN.nullDN(), "PLAIN", |
| | | credentials.toByteString()); |
| | | |
| | | // Check authentication result. |
| | | assertEquals(bind.getResultCode(), allow ? ResultCode.SUCCESS |
| | | : ResultCode.INVALID_CREDENTIALS); |
| | | |
| | | // Verify interaction with the policy/state. |
| | | assertTrue(policy.isStateFinalized()); |
| | | assertFalse(policy.isPolicyFinalized()); |
| | | assertEquals(policy.getMatchedPassword(), "password"); |
| | | } |
| | | finally |
| | | { |
| | | DirectoryServer.deregisterAuthenticationPolicy(policyDN); |
| | | assertTrue(policy.isPolicyFinalized()); |
| | | } |
| | | } |
| | | } |