From f110c97d39a464a8cc6563799392a5bca9ee0182 Mon Sep 17 00:00:00 2001
From: neil_a_wilson <neil_a_wilson@localhost>
Date: Mon, 12 Feb 2007 16:39:30 +0000
Subject: [PATCH] Implement support for the proxied-auth privilege, which will be required in order to use the proxied authorization control. This privilege is also used to determine whether a user can specify an alternate authorization identity for the SASL DIGEST-MD5 and PLAIN mechanisms.
---
opendj-sdk/opends/src/server/org/opends/server/core/DeleteOperation.java | 27
opendj-sdk/opends/src/server/org/opends/server/extensions/DigestMD5SASLMechanismHandler.java | 172 ++++
opendj-sdk/opends/src/server/org/opends/server/core/ModifyOperation.java | 26
opendj-sdk/opends/src/server/org/opends/server/core/AddOperation.java | 26
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/types/PrivilegeTestCase.java | 1155 +++++++++++++++++++++++++++++
opendj-sdk/opends/src/server/org/opends/server/core/CompareOperation.java | 26
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/core/TestModifyDNOperation.java | 73
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/core/CompareOperationTestCase.java | 56
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/DigestMD5SASLMechanismHandlerTestCase.java | 178 ++++
opendj-sdk/opends/src/server/org/opends/server/core/ModifyDNOperation.java | 27
opendj-sdk/opends/src/server/org/opends/server/messages/CoreMessages.java | 13
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/PlainSASLMechanismHandlerTestCase.java | 125 +++
opendj-sdk/opends/src/server/org/opends/server/messages/ExtensionsMessages.java | 174 ++++
opendj-sdk/opends/src/server/org/opends/server/types/AuthenticationInfo.java | 15
opendj-sdk/opends/src/server/org/opends/server/core/SearchOperation.java | 79 +
opendj-sdk/opends/src/server/org/opends/server/extensions/PlainSASLMechanismHandler.java | 157 +++
16 files changed, 2,202 insertions(+), 127 deletions(-)
diff --git a/opendj-sdk/opends/src/server/org/opends/server/core/AddOperation.java b/opendj-sdk/opends/src/server/org/opends/server/core/AddOperation.java
index 6d0bd25..6c79f9f 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/core/AddOperation.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/core/AddOperation.java
@@ -1775,6 +1775,17 @@
}
else if (oid.equals(OID_PROXIED_AUTH_V1))
{
+ // The requester must have the PROXIED_AUTH privilige in order to
+ // be able to use this control.
+ if (! clientConnection.hasPrivilege(Privilege.PROXIED_AUTH, this))
+ {
+ int msgID = MSGID_PROXYAUTH_INSUFFICIENT_PRIVILEGES;
+ appendErrorMessage(getMessage(msgID));
+ setResultCode(ResultCode.AUTHORIZATION_DENIED);
+ break addProcessing;
+ }
+
+
ProxiedAuthV1Control proxyControl;
if (c instanceof ProxiedAuthV1Control)
{
@@ -1814,12 +1825,21 @@
}
- // FIXME -- Should we specifically check permissions here, or let
- // the earlier access control checks handle it?
setAuthorizationEntry(authorizationEntry);
}
else if (oid.equals(OID_PROXIED_AUTH_V2))
{
+ // The requester must have the PROXIED_AUTH privilige in order to
+ // be able to use this control.
+ if (! clientConnection.hasPrivilege(Privilege.PROXIED_AUTH, this))
+ {
+ int msgID = MSGID_PROXYAUTH_INSUFFICIENT_PRIVILEGES;
+ appendErrorMessage(getMessage(msgID));
+ setResultCode(ResultCode.AUTHORIZATION_DENIED);
+ break addProcessing;
+ }
+
+
ProxiedAuthV2Control proxyControl;
if (c instanceof ProxiedAuthV2Control)
{
@@ -1859,8 +1879,6 @@
}
- // FIXME -- Should we specifically check permissions here, or let
- // the earlier access control checks handle it?
setAuthorizationEntry(authorizationEntry);
}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/core/CompareOperation.java b/opendj-sdk/opends/src/server/org/opends/server/core/CompareOperation.java
index 221cc91..abf3204 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/core/CompareOperation.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/core/CompareOperation.java
@@ -829,6 +829,17 @@
}
else if (oid.equals(OID_PROXIED_AUTH_V1))
{
+ // The requester must have the PROXIED_AUTH privilige in order to
+ // be able to use this control.
+ if (! clientConnection.hasPrivilege(Privilege.PROXIED_AUTH, this))
+ {
+ int msgID = MSGID_PROXYAUTH_INSUFFICIENT_PRIVILEGES;
+ appendErrorMessage(getMessage(msgID));
+ setResultCode(ResultCode.AUTHORIZATION_DENIED);
+ break compareProcessing;
+ }
+
+
ProxiedAuthV1Control proxyControl;
if (c instanceof ProxiedAuthV1Control)
{
@@ -868,12 +879,21 @@
}
- // FIXME -- Should we specifically check permissions here, or let
- // the earlier access control checks handle it?
setAuthorizationEntry(authorizationEntry);
}
else if (oid.equals(OID_PROXIED_AUTH_V2))
{
+ // The requester must have the PROXIED_AUTH privilige in order to
+ // be able to use this control.
+ if (! clientConnection.hasPrivilege(Privilege.PROXIED_AUTH, this))
+ {
+ int msgID = MSGID_PROXYAUTH_INSUFFICIENT_PRIVILEGES;
+ appendErrorMessage(getMessage(msgID));
+ setResultCode(ResultCode.AUTHORIZATION_DENIED);
+ break compareProcessing;
+ }
+
+
ProxiedAuthV2Control proxyControl;
if (c instanceof ProxiedAuthV2Control)
{
@@ -913,8 +933,6 @@
}
- // FIXME -- Should we specifically check permissions here, or let
- // the earlier access control checks handle it?
setAuthorizationEntry(authorizationEntry);
}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/core/DeleteOperation.java b/opendj-sdk/opends/src/server/org/opends/server/core/DeleteOperation.java
index 94748e9..5286f97 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/core/DeleteOperation.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/core/DeleteOperation.java
@@ -61,6 +61,7 @@
import org.opends.server.types.ErrorLogSeverity;
import org.opends.server.types.LockManager;
import org.opends.server.types.OperationType;
+import org.opends.server.types.Privilege;
import org.opends.server.types.ResultCode;
import org.opends.server.types.SearchFilter;
import org.opends.server.types.SearchResultEntry;
@@ -793,6 +794,17 @@
}
else if (oid.equals(OID_PROXIED_AUTH_V1))
{
+ // The requester must have the PROXIED_AUTH privilige in order to
+ // be able to use this control.
+ if (! clientConnection.hasPrivilege(Privilege.PROXIED_AUTH, this))
+ {
+ int msgID = MSGID_PROXYAUTH_INSUFFICIENT_PRIVILEGES;
+ appendErrorMessage(getMessage(msgID));
+ setResultCode(ResultCode.AUTHORIZATION_DENIED);
+ break deleteProcessing;
+ }
+
+
ProxiedAuthV1Control proxyControl;
if (c instanceof ProxiedAuthV1Control)
{
@@ -832,12 +844,21 @@
}
- // FIXME -- Should we specifically check permissions here, or let
- // the earlier access control checks handle it?
setAuthorizationEntry(authorizationEntry);
}
else if (oid.equals(OID_PROXIED_AUTH_V2))
{
+ // The requester must have the PROXIED_AUTH privilige in order to
+ // be able to use this control.
+ if (! clientConnection.hasPrivilege(Privilege.PROXIED_AUTH, this))
+ {
+ int msgID = MSGID_PROXYAUTH_INSUFFICIENT_PRIVILEGES;
+ appendErrorMessage(getMessage(msgID));
+ setResultCode(ResultCode.AUTHORIZATION_DENIED);
+ break deleteProcessing;
+ }
+
+
ProxiedAuthV2Control proxyControl;
if (c instanceof ProxiedAuthV2Control)
{
@@ -877,8 +898,6 @@
}
- // FIXME -- Should we specifically check permissions here, or let
- // the earlier access control checks handle it?
setAuthorizationEntry(authorizationEntry);
}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/core/ModifyDNOperation.java b/opendj-sdk/opends/src/server/org/opends/server/core/ModifyDNOperation.java
index 46a6402..e0a918d 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/core/ModifyDNOperation.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/core/ModifyDNOperation.java
@@ -69,6 +69,7 @@
import org.opends.server.types.Modification;
import org.opends.server.types.ModificationType;
import org.opends.server.types.OperationType;
+import org.opends.server.types.Privilege;
import org.opends.server.types.RDN;
import org.opends.server.types.ResultCode;
import org.opends.server.types.SearchFilter;
@@ -1284,6 +1285,17 @@
}
else if (oid.equals(OID_PROXIED_AUTH_V1))
{
+ // The requester must have the PROXIED_AUTH privilige in order to
+ // be able to use this control.
+ if (! clientConnection.hasPrivilege(Privilege.PROXIED_AUTH, this))
+ {
+ int msgID = MSGID_PROXYAUTH_INSUFFICIENT_PRIVILEGES;
+ appendErrorMessage(getMessage(msgID));
+ setResultCode(ResultCode.AUTHORIZATION_DENIED);
+ break modifyDNProcessing;
+ }
+
+
ProxiedAuthV1Control proxyControl;
if (c instanceof ProxiedAuthV1Control)
{
@@ -1323,12 +1335,21 @@
}
- // FIXME -- Should we specifically check permissions here, or let
- // the earlier access control checks handle it?
setAuthorizationEntry(authorizationEntry);
}
else if (oid.equals(OID_PROXIED_AUTH_V2))
{
+ // The requester must have the PROXIED_AUTH privilige in order to
+ // be able to use this control.
+ if (! clientConnection.hasPrivilege(Privilege.PROXIED_AUTH, this))
+ {
+ int msgID = MSGID_PROXYAUTH_INSUFFICIENT_PRIVILEGES;
+ appendErrorMessage(getMessage(msgID));
+ setResultCode(ResultCode.AUTHORIZATION_DENIED);
+ break modifyDNProcessing;
+ }
+
+
ProxiedAuthV2Control proxyControl;
if (c instanceof ProxiedAuthV2Control)
{
@@ -1368,8 +1389,6 @@
}
- // FIXME -- Should we specifically check permissions here, or let
- // the earlier access control checks handle it?
setAuthorizationEntry(authorizationEntry);
}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/core/ModifyOperation.java b/opendj-sdk/opends/src/server/org/opends/server/core/ModifyOperation.java
index be01a29..099f0d2 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/core/ModifyOperation.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/core/ModifyOperation.java
@@ -1087,6 +1087,17 @@
}
else if (oid.equals(OID_PROXIED_AUTH_V1))
{
+ // The requester must have the PROXIED_AUTH privilige in order to
+ // be able to use this control.
+ if (! clientConnection.hasPrivilege(Privilege.PROXIED_AUTH, this))
+ {
+ int msgID = MSGID_PROXYAUTH_INSUFFICIENT_PRIVILEGES;
+ appendErrorMessage(getMessage(msgID));
+ setResultCode(ResultCode.AUTHORIZATION_DENIED);
+ break modifyProcessing;
+ }
+
+
ProxiedAuthV1Control proxyControl;
if (c instanceof ProxiedAuthV1Control)
{
@@ -1126,12 +1137,21 @@
}
- // FIXME -- Should we specifically check permissions here, or let
- // the earlier access control checks handle it?
setAuthorizationEntry(authorizationEntry);
}
else if (oid.equals(OID_PROXIED_AUTH_V2))
{
+ // The requester must have the PROXIED_AUTH privilige in order to
+ // be able to use this control.
+ if (! clientConnection.hasPrivilege(Privilege.PROXIED_AUTH, this))
+ {
+ int msgID = MSGID_PROXYAUTH_INSUFFICIENT_PRIVILEGES;
+ appendErrorMessage(getMessage(msgID));
+ setResultCode(ResultCode.AUTHORIZATION_DENIED);
+ break modifyProcessing;
+ }
+
+
ProxiedAuthV2Control proxyControl;
if (c instanceof ProxiedAuthV2Control)
{
@@ -1171,8 +1191,6 @@
}
- // FIXME -- Should we specifically check permissions here, or let
- // the earlier access control checks handle it?
setAuthorizationEntry(authorizationEntry);
}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/core/SearchOperation.java b/opendj-sdk/opends/src/server/org/opends/server/core/SearchOperation.java
index d8b6f44..15a319a 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/core/SearchOperation.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/core/SearchOperation.java
@@ -66,6 +66,7 @@
import org.opends.server.types.Entry;
import org.opends.server.types.FilterType;
import org.opends.server.types.OperationType;
+import org.opends.server.types.Privilege;
import org.opends.server.types.ResultCode;
import org.opends.server.types.SearchFilter;
import org.opends.server.types.SearchResultEntry;
@@ -1760,6 +1761,17 @@
}
else if (oid.equals(OID_PROXIED_AUTH_V1))
{
+ // The requester must have the PROXIED_AUTH privilige in order to be
+ // able to use this control.
+ if (! clientConnection.hasPrivilege(Privilege.PROXIED_AUTH, this))
+ {
+ int msgID = MSGID_PROXYAUTH_INSUFFICIENT_PRIVILEGES;
+ appendErrorMessage(getMessage(msgID));
+ setResultCode(ResultCode.AUTHORIZATION_DENIED);
+ break searchProcessing;
+ }
+
+
ProxiedAuthV1Control proxyControl;
if (c instanceof ProxiedAuthV1Control)
{
@@ -1783,28 +1795,37 @@
}
- Entry authorizationEntry;
- try
- {
- authorizationEntry = proxyControl.getAuthorizationEntry();
- }
- catch (DirectoryException de)
- {
- assert debugException(CLASS_NAME, "run", de);
+ Entry authorizationEntry;
+ try
+ {
+ authorizationEntry = proxyControl.getAuthorizationEntry();
+ }
+ catch (DirectoryException de)
+ {
+ assert debugException(CLASS_NAME, "run", de);
- setResultCode(de.getResultCode());
- appendErrorMessage(de.getErrorMessage());
+ setResultCode(de.getResultCode());
+ appendErrorMessage(de.getErrorMessage());
- break searchProcessing;
- }
+ break searchProcessing;
+ }
- // FIXME -- Should we specifically check permissions here, or let
- // the earlier access control checks handle it?
- setAuthorizationEntry(authorizationEntry);
+ setAuthorizationEntry(authorizationEntry);
}
else if (oid.equals(OID_PROXIED_AUTH_V2))
{
+ // The requester must have the PROXIED_AUTH privilige in order to be
+ // able to use this control.
+ if (! clientConnection.hasPrivilege(Privilege.PROXIED_AUTH, this))
+ {
+ int msgID = MSGID_PROXYAUTH_INSUFFICIENT_PRIVILEGES;
+ appendErrorMessage(getMessage(msgID));
+ setResultCode(ResultCode.AUTHORIZATION_DENIED);
+ break searchProcessing;
+ }
+
+
ProxiedAuthV2Control proxyControl;
if (c instanceof ProxiedAuthV2Control)
{
@@ -1828,25 +1849,23 @@
}
- Entry authorizationEntry;
- try
- {
- authorizationEntry = proxyControl.getAuthorizationEntry();
- }
- catch (DirectoryException de)
- {
- assert debugException(CLASS_NAME, "run", de);
+ Entry authorizationEntry;
+ try
+ {
+ authorizationEntry = proxyControl.getAuthorizationEntry();
+ }
+ catch (DirectoryException de)
+ {
+ assert debugException(CLASS_NAME, "run", de);
- setResultCode(de.getResultCode());
- appendErrorMessage(de.getErrorMessage());
+ setResultCode(de.getResultCode());
+ appendErrorMessage(de.getErrorMessage());
- break searchProcessing;
- }
+ break searchProcessing;
+ }
- // FIXME -- Should we specifically check permissions here, or let
- // the earlier access control checks handle it?
- setAuthorizationEntry(authorizationEntry);
+ setAuthorizationEntry(authorizationEntry);
}
else if (oid.equals(OID_PERSISTENT_SEARCH))
{
diff --git a/opendj-sdk/opends/src/server/org/opends/server/extensions/DigestMD5SASLMechanismHandler.java b/opendj-sdk/opends/src/server/org/opends/server/extensions/DigestMD5SASLMechanismHandler.java
index 7036ebe..9a3303a 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/extensions/DigestMD5SASLMechanismHandler.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/extensions/DigestMD5SASLMechanismHandler.java
@@ -55,6 +55,7 @@
import org.opends.server.core.DirectoryServer;
import org.opends.server.core.PasswordPolicyState;
import org.opends.server.protocols.asn1.ASN1OctetString;
+import org.opends.server.protocols.internal.InternalClientConnection;
import org.opends.server.types.AuthenticationInfo;
import org.opends.server.types.ByteString;
import org.opends.server.types.ConfigChangeResult;
@@ -66,6 +67,7 @@
import org.opends.server.types.ErrorLogSeverity;
import org.opends.server.types.InitializationException;
import org.opends.server.types.LockManager;
+import org.opends.server.types.Privilege;
import org.opends.server.types.ResultCode;
import org.opends.server.util.Base64;
@@ -893,6 +895,170 @@
}
+ Entry authZEntry = userEntry;
+ if (responseAuthzID != null)
+ {
+ if (responseAuthzID.length() == 0)
+ {
+ // The authorization ID must not be an empty string.
+ bindOperation.setResultCode(ResultCode.INVALID_CREDENTIALS);
+
+ int msgID = MSGID_SASLDIGESTMD5_EMPTY_AUTHZID;
+ String message = getMessage(msgID);
+ bindOperation.setAuthFailureReason(msgID, message);
+ return;
+ }
+ else if (! responseAuthzID.equals(responseUserName))
+ {
+ String lowerAuthzID = toLowerCase(responseAuthzID);
+
+ if (lowerAuthzID.startsWith("dn:"))
+ {
+ DN authzDN;
+ try
+ {
+ authzDN = DN.decode(responseAuthzID.substring(3));
+ }
+ catch (DirectoryException de)
+ {
+ assert debugException(CLASS_NAME, "processSASLBind", de);
+
+ bindOperation.setResultCode(ResultCode.INVALID_CREDENTIALS);
+
+ int msgID = MSGID_SASLDIGESTMD5_AUTHZID_INVALID_DN;
+ String message = getMessage(msgID, responseAuthzID,
+ de.getErrorMessage());
+ bindOperation.setAuthFailureReason(msgID, message);
+ return;
+ }
+
+ DN actualAuthzDN = DirectoryServer.getActualRootBindDN(authzDN);
+ if (actualAuthzDN != null)
+ {
+ authzDN = actualAuthzDN;
+ }
+
+ if (! authzDN.equals(userEntry.getDN()))
+ {
+ AuthenticationInfo tempAuthInfo =
+ new AuthenticationInfo(userEntry,
+ DirectoryServer.isRootDN(userEntry.getDN()));
+ InternalClientConnection tempConn =
+ new InternalClientConnection(tempAuthInfo);
+ if (! tempConn.hasPrivilege(Privilege.PROXIED_AUTH, bindOperation))
+ {
+ bindOperation.setResultCode(ResultCode.INVALID_CREDENTIALS);
+
+ int msgID = MSGID_SASLDIGESTMD5_AUTHZID_INSUFFICIENT_PRIVILEGES;
+ String message = getMessage(msgID,
+ String.valueOf(userEntry.getDN()));
+ bindOperation.setAuthFailureReason(msgID, message);
+ return;
+ }
+
+ if (authzDN.isNullDN())
+ {
+ authZEntry = null;
+ }
+ else
+ {
+ try
+ {
+ authZEntry = DirectoryServer.getEntry(authzDN);
+ if (authZEntry == null)
+ {
+ bindOperation.setResultCode(ResultCode.INVALID_CREDENTIALS);
+
+ int msgID = MSGID_SASLDIGESTMD5_AUTHZID_NO_SUCH_ENTRY;
+ String message = getMessage(msgID, String.valueOf(authzDN));
+ bindOperation.setAuthFailureReason(msgID, message);
+ return;
+ }
+ }
+ catch (DirectoryException de)
+ {
+ assert debugException(CLASS_NAME, "processSASLBind", de);
+
+ bindOperation.setResultCode(ResultCode.INVALID_CREDENTIALS);
+
+ int msgID = MSGID_SASLDIGESTMD5_AUTHZID_CANNOT_GET_ENTRY;
+ String message = getMessage(msgID, String.valueOf(authzDN),
+ de.getErrorMessage());
+ bindOperation.setAuthFailureReason(msgID, message);
+ return;
+ }
+ }
+ }
+ }
+ else
+ {
+ String idStr;
+ if (lowerAuthzID.startsWith("u:"))
+ {
+ idStr = responseAuthzID.substring(2);
+ }
+ else
+ {
+ idStr = responseAuthzID;
+ }
+
+ if (idStr.length() == 0)
+ {
+ authZEntry = null;
+ }
+ else
+ {
+ try
+ {
+ authZEntry = identityMapper.getEntryForID(idStr);
+ if (authZEntry == null)
+ {
+ bindOperation.setResultCode(ResultCode.INVALID_CREDENTIALS);
+
+ int msgID = MSGID_SASLDIGESTMD5_AUTHZID_NO_MAPPED_ENTRY;
+ String message = getMessage(msgID, responseAuthzID);
+ bindOperation.setAuthFailureReason(msgID, message);
+ return;
+ }
+ }
+ catch (DirectoryException de)
+ {
+ assert debugException(CLASS_NAME, "processSASLBind", de);
+
+ bindOperation.setResultCode(ResultCode.INVALID_CREDENTIALS);
+
+ int msgID = MSGID_SASLDIGESTMD5_CANNOT_MAP_AUTHZID;
+ String message = getMessage(msgID, responseAuthzID,
+ de.getErrorMessage());
+ bindOperation.setAuthFailureReason(msgID, message);
+ return;
+ }
+ }
+
+ if ((authZEntry == null) ||
+ (! authZEntry.getDN().equals(userEntry.getDN())))
+ {
+ AuthenticationInfo tempAuthInfo =
+ new AuthenticationInfo(userEntry,
+ DirectoryServer.isRootDN(userEntry.getDN()));
+ InternalClientConnection tempConn =
+ new InternalClientConnection(tempAuthInfo);
+ if (! tempConn.hasPrivilege(Privilege.PROXIED_AUTH, bindOperation))
+ {
+ bindOperation.setResultCode(ResultCode.INVALID_CREDENTIALS);
+
+ int msgID = MSGID_SASLDIGESTMD5_AUTHZID_INSUFFICIENT_PRIVILEGES;
+ String message = getMessage(msgID,
+ String.valueOf(userEntry.getDN()));
+ bindOperation.setAuthFailureReason(msgID, message);
+ return;
+ }
+ }
+ }
+ }
+ }
+
+
// Get the clear-text passwords from the user entry, if there are any.
List<ByteString> clearPasswords;
try
@@ -968,9 +1134,6 @@
}
- // FIXME -- Need to do something with the authzid.
-
-
// Generate the response auth element to include in the response to the
// client.
byte[] responseAuth;
@@ -1011,7 +1174,8 @@
AuthenticationInfo authInfo =
- new AuthenticationInfo(userEntry, SASL_MECHANISM_DIGEST_MD5,
+ new AuthenticationInfo(userEntry, authZEntry,
+ SASL_MECHANISM_DIGEST_MD5,
DirectoryServer.isRootDN(userEntry.getDN()));
bindOperation.setAuthenticationInfo(authInfo);
return;
diff --git a/opendj-sdk/opends/src/server/org/opends/server/extensions/PlainSASLMechanismHandler.java b/opendj-sdk/opends/src/server/org/opends/server/extensions/PlainSASLMechanismHandler.java
index 3adb6c0..7afe91d 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/extensions/PlainSASLMechanismHandler.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/extensions/PlainSASLMechanismHandler.java
@@ -44,6 +44,7 @@
import org.opends.server.core.DirectoryServer;
import org.opends.server.core.PasswordPolicyState;
import org.opends.server.protocols.asn1.ASN1OctetString;
+import org.opends.server.protocols.internal.InternalClientConnection;
import org.opends.server.types.AuthenticationInfo;
import org.opends.server.types.ByteString;
import org.opends.server.types.ConfigChangeResult;
@@ -52,6 +53,7 @@
import org.opends.server.types.Entry;
import org.opends.server.types.InitializationException;
import org.opends.server.types.LockManager;
+import org.opends.server.types.Privilege;
import org.opends.server.types.ResultCode;
import static org.opends.server.config.ConfigConstants.*;
@@ -398,6 +400,156 @@
}
+ // If an authorization ID was provided, then make sure that it is
+ // acceptable.
+ Entry authZEntry = userEntry;
+ if (authzID != null)
+ {
+ String lowerAuthzID = toLowerCase(authzID);
+ if (lowerAuthzID.startsWith("dn:"))
+ {
+ DN authzDN;
+ try
+ {
+ authzDN = DN.decode(authzID.substring(3));
+ }
+ catch (DirectoryException de)
+ {
+ assert debugException(CLASS_NAME, "processSASLBind", de);
+
+ bindOperation.setResultCode(ResultCode.INVALID_CREDENTIALS);
+
+ int msgID = MSGID_SASLPLAIN_AUTHZID_INVALID_DN;
+ String message = getMessage(msgID, authzID, de.getErrorMessage());
+ bindOperation.setAuthFailureReason(msgID, message);
+ return;
+ }
+
+ DN actualAuthzDN = DirectoryServer.getActualRootBindDN(authzDN);
+ if (actualAuthzDN != null)
+ {
+ authzDN = actualAuthzDN;
+ }
+
+ if (! authzDN.equals(userEntry.getDN()))
+ {
+ AuthenticationInfo tempAuthInfo =
+ new AuthenticationInfo(userEntry,
+ DirectoryServer.isRootDN(userEntry.getDN()));
+ InternalClientConnection tempConn =
+ new InternalClientConnection(tempAuthInfo);
+ if (! tempConn.hasPrivilege(Privilege.PROXIED_AUTH, bindOperation))
+ {
+ bindOperation.setResultCode(ResultCode.INVALID_CREDENTIALS);
+
+ int msgID = MSGID_SASLPLAIN_AUTHZID_INSUFFICIENT_PRIVILEGES;
+ String message = getMessage(msgID,
+ String.valueOf(userEntry.getDN()));
+ bindOperation.setAuthFailureReason(msgID, message);
+ return;
+ }
+
+ if (authzDN.isNullDN())
+ {
+ authZEntry = null;
+ }
+ else
+ {
+ try
+ {
+ authZEntry = DirectoryServer.getEntry(authzDN);
+ if (authZEntry == null)
+ {
+ bindOperation.setResultCode(ResultCode.INVALID_CREDENTIALS);
+
+ int msgID = MSGID_SASLPLAIN_AUTHZID_NO_SUCH_ENTRY;
+ String message = getMessage(msgID, String.valueOf(authzDN));
+ bindOperation.setAuthFailureReason(msgID, message);
+ return;
+ }
+ }
+ catch (DirectoryException de)
+ {
+ assert debugException(CLASS_NAME, "processSASLBind", de);
+
+ bindOperation.setResultCode(ResultCode.INVALID_CREDENTIALS);
+
+ int msgID = MSGID_SASLPLAIN_AUTHZID_CANNOT_GET_ENTRY;
+ String message = getMessage(msgID, String.valueOf(authzDN),
+ de.getErrorMessage());
+ bindOperation.setAuthFailureReason(msgID, message);
+ return;
+ }
+ }
+ }
+ }
+ else
+ {
+ String idStr;
+ if (lowerAuthzID.startsWith("u:"))
+ {
+ idStr = authzID.substring(2);
+ }
+ else
+ {
+ idStr = authzID;
+ }
+
+ if (idStr.length() == 0)
+ {
+ authZEntry = null;
+ }
+ else
+ {
+ try
+ {
+ authZEntry = identityMapper.getEntryForID(idStr);
+ if (authZEntry == null)
+ {
+ bindOperation.setResultCode(ResultCode.INVALID_CREDENTIALS);
+
+ int msgID = MSGID_SASLPLAIN_AUTHZID_NO_MAPPED_ENTRY;
+ String message = getMessage(msgID, authzID);
+ bindOperation.setAuthFailureReason(msgID, message);
+ return;
+ }
+ }
+ catch (DirectoryException de)
+ {
+ assert debugException(CLASS_NAME, "processSASLBind", de);
+
+ bindOperation.setResultCode(ResultCode.INVALID_CREDENTIALS);
+
+ int msgID = MSGID_SASLPLAIN_AUTHZID_CANNOT_MAP_AUTHZID;
+ String message = getMessage(msgID, authzID, de.getErrorMessage());
+ bindOperation.setAuthFailureReason(msgID, message);
+ return;
+ }
+ }
+
+ if ((authZEntry == null) ||
+ (! authZEntry.getDN().equals(userEntry.getDN())))
+ {
+ AuthenticationInfo tempAuthInfo =
+ new AuthenticationInfo(userEntry,
+ DirectoryServer.isRootDN(userEntry.getDN()));
+ InternalClientConnection tempConn =
+ new InternalClientConnection(tempAuthInfo);
+ if (! tempConn.hasPrivilege(Privilege.PROXIED_AUTH, bindOperation))
+ {
+ bindOperation.setResultCode(ResultCode.INVALID_CREDENTIALS);
+
+ int msgID = MSGID_SASLPLAIN_AUTHZID_INSUFFICIENT_PRIVILEGES;
+ String message = getMessage(msgID,
+ String.valueOf(userEntry.getDN()));
+ bindOperation.setAuthFailureReason(msgID, message);
+ return;
+ }
+ }
+ }
+ }
+
+
// Get the password policy for the user and use it to determine if the
// provided password was correct.
try
@@ -428,14 +580,11 @@
}
- // FIXME -- Figure out what to do with the authzID if one was provided.
-
-
// If we've gotten here, then the authentication was successful.
bindOperation.setResultCode(ResultCode.SUCCESS);
AuthenticationInfo authInfo =
- new AuthenticationInfo(userEntry, SASL_MECHANISM_PLAIN,
+ new AuthenticationInfo(userEntry, authZEntry, SASL_MECHANISM_PLAIN,
DirectoryServer.isRootDN(userEntry.getDN()));
bindOperation.setAuthenticationInfo(authInfo);
return;
diff --git a/opendj-sdk/opends/src/server/org/opends/server/messages/CoreMessages.java b/opendj-sdk/opends/src/server/org/opends/server/messages/CoreMessages.java
index 4a6f374..160a34f 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/messages/CoreMessages.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/messages/CoreMessages.java
@@ -6229,6 +6229,16 @@
/**
+ * The message ID for the message that will be used when a client attempts to
+ * use the proxied authorization control without sufficient privileges. This
+ * does not take any arguments.
+ */
+ public static final int MSGID_PROXYAUTH_INSUFFICIENT_PRIVILEGES =
+ CATEGORY_MASK_CORE | SEVERITY_MASK_MILD_ERROR | 595;
+
+
+
+ /**
* Associates a set of generic messages with the message IDs defined
* in this class.
*/
@@ -8423,6 +8433,9 @@
registerMessage(MSGID_CLIENTCONNECTION_AUDIT_HASPRIVILEGES,
"hasPrivilege determination for connID=%d opID=%d " +
"requesterDN=\"%s\" privilegeSet=\"%s\" result=%b");
+ registerMessage(MSGID_PROXYAUTH_INSUFFICIENT_PRIVILEGES,
+ "You do not have sufficient privileges to use the " +
+ "proxied authorization control.");
}
}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/messages/ExtensionsMessages.java b/opendj-sdk/opends/src/server/org/opends/server/messages/ExtensionsMessages.java
index 66e04e5..56fba4d 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/messages/ExtensionsMessages.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/messages/ExtensionsMessages.java
@@ -4150,6 +4150,141 @@
/**
+ * The message ID for the message that will be used if the DIGEST-MD5 authzid
+ * is the empty string. This does not take any arguments.
+ */
+ public static final int MSGID_SASLDIGESTMD5_EMPTY_AUTHZID =
+ CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_MILD_ERROR | 393;
+
+
+
+ /**
+ * The message ID for the message that will be used if the DIGEST-MD5 authzid
+ * contained an invalid DN. This takes two arguments, which are the authzid
+ * and the reason that it was invalid.
+ */
+ public static final int MSGID_SASLDIGESTMD5_AUTHZID_INVALID_DN =
+ CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_MILD_ERROR | 394;
+
+
+
+ /**
+ * The message ID for the message that will be used if the authenticating user
+ * does not have sufficient privilege to specify an authorization identity
+ * that is different from the authentication identity. This takes a single
+ * argument, which is the DN of the authentication identity.
+ */
+ public static final int MSGID_SASLDIGESTMD5_AUTHZID_INSUFFICIENT_PRIVILEGES =
+ CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_MILD_ERROR | 395;
+
+
+
+ /**
+ * The message ID for the message that will be used if the DIGEST-MD5 authzid
+ * references an entry that does not exist. This takes a single argument,
+ * which is the DN of the target entry.
+ */
+ public static final int MSGID_SASLDIGESTMD5_AUTHZID_NO_SUCH_ENTRY =
+ CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_MILD_ERROR | 396;
+
+
+
+ /**
+ * The message ID for the message that will be used if an error occurs while
+ * attempting to get the entry for the authorization identity. This takes two
+ * arguments, which are the authorization DN and a message explaining the
+ * problem that occurred.
+ */
+ public static final int MSGID_SASLDIGESTMD5_AUTHZID_CANNOT_GET_ENTRY =
+ CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_MILD_ERROR | 397;
+
+
+
+ /**
+ * The message ID for the message that will be used if the "u:"-form
+ * authorization ID cannot be mapped to a user entry. This takes a single
+ * argument, which is the authzID string.
+ */
+ public static final int MSGID_SASLDIGESTMD5_AUTHZID_NO_MAPPED_ENTRY =
+ CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_MILD_ERROR | 398;
+
+
+
+ /**
+ * The message ID for the message that will be used if an error occurs while
+ * attempting to map the "u:"-form authorization ID to a user entry. This
+ * takes two arguments, which are the authzID string and a message explaining
+ * the problem that occurred.
+ */
+ public static final int MSGID_SASLDIGESTMD5_CANNOT_MAP_AUTHZID =
+ CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_MILD_ERROR | 399;
+
+
+
+ /**
+ * The message ID for the message that will be used if the authorization ID is
+ * a malformed DN. This takes two arguments, which are the authorization ID
+ * string and a message explaining the problem that occurred.
+ */
+ public static final int MSGID_SASLPLAIN_AUTHZID_INVALID_DN =
+ CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_MILD_ERROR | 400;
+
+
+
+ /**
+ * The message ID for the message that will be used if the authenticating user
+ * attempts to provide an alternate authorization ID but does not have
+ * sufficient privileges to do so. This takes a single argument, which is the
+ * DN of the authenticating user.
+ */
+ public static final int MSGID_SASLPLAIN_AUTHZID_INSUFFICIENT_PRIVILEGES =
+ CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_MILD_ERROR | 401;
+
+
+
+ /**
+ * The message ID for the message that will be used if the authorization ID
+ * contains the DN of an entry that does not exist. This takes a single
+ * argument, which is the authorization DN.
+ */
+ public static final int MSGID_SASLPLAIN_AUTHZID_NO_SUCH_ENTRY =
+ CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_MILD_ERROR | 402;
+
+
+
+ /**
+ * The message ID for the message that will be used if a problem occurs while
+ * trying to get the entry for the authorization DN. This takes two
+ * arguments, which are the authorization DN and a message explaining the
+ * problem that occurred.
+ */
+ public static final int MSGID_SASLPLAIN_AUTHZID_CANNOT_GET_ENTRY =
+ CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_MILD_ERROR | 403;
+
+
+
+ /**
+ * The message ID for the message that will be used if the authorization ID
+ * specifies a username that does not map to an entry. This takes a single
+ * argument, which is the authorization ID string.
+ */
+ public static final int MSGID_SASLPLAIN_AUTHZID_NO_MAPPED_ENTRY =
+ CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_MILD_ERROR | 404;
+
+
+
+ /**
+ * The message ID for the message that will be used if an error occurs while
+ * trying to map the authorization ID username to an entry. This takes two
+ * arguments, which are the authorization ID string and a message explaining
+ * the problem that occurred.
+ */
+ public static final int MSGID_SASLPLAIN_AUTHZID_CANNOT_MAP_AUTHZID =
+ CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_MILD_ERROR | 405;
+
+
+
+ /**
* Associates a set of generic messages with the message IDs defined in this
* class.
*/
@@ -5084,6 +5219,24 @@
registerMessage(MSGID_SASLPLAIN_NO_MATCHING_ENTRIES,
"The server was not able to find any user entries for " +
"the provided authentication ID of %s.");
+ registerMessage(MSGID_SASLPLAIN_AUTHZID_INVALID_DN,
+ "The provided authorization ID %s contained an invalid " +
+ "DN: %s.");
+ registerMessage(MSGID_SASLPLAIN_AUTHZID_INSUFFICIENT_PRIVILEGES,
+ "The authenticating user %s does not have sufficient " +
+ "privileges to specify an alternate authorization ID.");
+ registerMessage(MSGID_SASLPLAIN_AUTHZID_NO_SUCH_ENTRY,
+ "The entry corresponding to authorization DN %s does not " +
+ "exist in the Directory Server.");
+ registerMessage(MSGID_SASLPLAIN_AUTHZID_CANNOT_GET_ENTRY,
+ "An error occurred while attempting to retrieve entry %s " +
+ "specified as the authorization ID: %s.");
+ registerMessage(MSGID_SASLPLAIN_AUTHZID_NO_MAPPED_ENTRY,
+ "No entry corresponding to authorization ID %s was found " +
+ "in the server.");
+ registerMessage(MSGID_SASLPLAIN_AUTHZID_CANNOT_MAP_AUTHZID,
+ "An error occurred while attempting to map authorization " +
+ "ID %s to a user entry: %s.");
registerMessage(MSGID_SASLPLAIN_NO_PW_ATTR,
"The SASL PLAIN authentication failed because the mapped " +
"user entry did not contain any values for the %s " +
@@ -5469,6 +5622,27 @@
registerMessage(MSGID_SASLDIGESTMD5_NO_MATCHING_ENTRIES,
"The server was not able to find any user entries for " +
"the provided username of %s.");
+ registerMessage(MSGID_SASLDIGESTMD5_EMPTY_AUTHZID,
+ "The provided authorization ID was empty, which is not " +
+ "allowed for DIGEST-MD5 authentication.");
+ registerMessage(MSGID_SASLDIGESTMD5_AUTHZID_INVALID_DN,
+ "The provided authorization ID %s contained an invalid " +
+ "DN: %s.");
+ registerMessage(MSGID_SASLDIGESTMD5_AUTHZID_INSUFFICIENT_PRIVILEGES,
+ "The authenticating user %s does not have sufficient " +
+ "privileges to assume a different authorization identity.");
+ registerMessage(MSGID_SASLDIGESTMD5_AUTHZID_NO_SUCH_ENTRY,
+ "The entry %s specified as the authorization identity " +
+ "does not exist.");
+ registerMessage(MSGID_SASLDIGESTMD5_AUTHZID_CANNOT_GET_ENTRY,
+ "The entry %s specified as the authorization identity " +
+ "could not be retrieved: %s.");
+ registerMessage(MSGID_SASLDIGESTMD5_AUTHZID_NO_MAPPED_ENTRY,
+ "The server was unable to find any entry corresponding " +
+ "to authorization ID %s.");
+ registerMessage(MSGID_SASLDIGESTMD5_CANNOT_MAP_AUTHZID,
+ "An error occurred while attempting to map authorization " +
+ "ID %s to a user entry: %s.");
registerMessage(MSGID_SASLDIGESTMD5_NO_PW_ATTR,
"The SASL DIGEST-MD5 authentication failed because the " +
"mapped user entry did not contain any values for the %s " +
diff --git a/opendj-sdk/opends/src/server/org/opends/server/types/AuthenticationInfo.java b/opendj-sdk/opends/src/server/org/opends/server/types/AuthenticationInfo.java
index a570693..bde9e7d 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/types/AuthenticationInfo.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/types/AuthenticationInfo.java
@@ -224,8 +224,9 @@
* @param authorizationEntry The entry of the user that will be
* used as the default authorization
* identity, or {@code null} to
- * indicate that it should be the same
- * as the authentication entry.
+ * indicate that the authorization
+ * identity should be the
+ * unauthenticated user.
* @param saslMechanism The SASL mechanism used to
* authenticate. This must be provided
* in all-uppercase characters and must
@@ -246,17 +247,9 @@
ensureNotNull(authenticationEntry, saslMechanism);
this.authenticationEntry = authenticationEntry;
+ this.authorizationEntry = authorizationEntry;
this.isRoot = isRoot;
- if (authorizationEntry == null)
- {
- this.authorizationEntry = authenticationEntry;
- }
- else
- {
- this.authorizationEntry = authorizationEntry;
- }
-
isAuthenticated = true;
mustChangePassword = false;
simplePassword = null;
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/core/CompareOperationTestCase.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/core/CompareOperationTestCase.java
index 347acd8..396fea5 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/core/CompareOperationTestCase.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/core/CompareOperationTestCase.java
@@ -22,7 +22,7 @@
* CDDL HEADER END
*
*
- * Portions Copyright 2006 Sun Microsystems, Inc.
+ * Portions Copyright 2006-2007 Sun Microsystems, Inc.
*/
package org.opends.server.core;
@@ -32,8 +32,10 @@
import org.opends.server.protocols.asn1.ASN1Reader;
import org.opends.server.protocols.asn1.ASN1Writer;
import org.opends.server.protocols.ldap.*;
+import org.opends.server.types.AuthenticationInfo;
import org.opends.server.types.Control;
import org.opends.server.types.ResultCode;
+import org.opends.server.types.DN;
import org.opends.server.types.Entry;
import org.opends.server.types.LockManager;
import org.opends.server.TestCaseUtils;
@@ -54,6 +56,7 @@
public class CompareOperationTestCase extends OperationTestCase
{
private Entry entry;
+ private InternalClientConnection proxyUserConn;
@BeforeClass
@@ -101,6 +104,25 @@
entry.getOperationalAttributes());
assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS);
assertNotNull(DirectoryServer.getEntry(entry.getDN()));
+
+ // Add a user capable of using the proxied authorization control.
+ TestCaseUtils.addEntry(
+ "dn: uid=proxy.user,o=test",
+ "objectClass: top",
+ "objectClass: person",
+ "objectClass: organizationalPerson",
+ "objectClass: inetOrgPerson",
+ "uid: proxy.user",
+ "givenName: Proxy",
+ "sn: User",
+ "cn: Proxy User",
+ "userPassword: password",
+ "ds-privilege-name: proxied-auth");
+
+ Entry proxyUserEntry =
+ DirectoryServer.getEntry(DN.decode("uid=proxy.user,o=test"));
+ AuthenticationInfo authInfo = new AuthenticationInfo(proxyUserEntry, false);
+ proxyUserConn = new InternalClientConnection(authInfo);
}
@@ -435,16 +457,14 @@
{
InvocationCounterPlugin.resetAllCounters();
- InternalClientConnection conn =
- InternalClientConnection.getRootConnection();
-
ProxiedAuthV1Control authV1Control =
new ProxiedAuthV1Control(new ASN1OctetString());
List<Control> controls = new ArrayList<Control>();
controls.add(authV1Control);
CompareOperation compareOperation =
- new CompareOperation(conn, InternalClientConnection.nextOperationID(),
+ new CompareOperation(proxyUserConn,
+ InternalClientConnection.nextOperationID(),
InternalClientConnection.nextMessageID(),
controls,
new ASN1OctetString(entry.getDN().toString()),
@@ -461,10 +481,9 @@
@Test
public void testCompareProxiedAuthV1Denied() throws Exception
{
- InvocationCounterPlugin.resetAllCounters();
- InternalClientConnection conn =
- InternalClientConnection.getRootConnection();
+
+ InvocationCounterPlugin.resetAllCounters();
ProxiedAuthV1Control authV1Control =
new ProxiedAuthV1Control(new ASN1OctetString("cn=nonexistent,o=test"));
@@ -472,7 +491,8 @@
controls.add(authV1Control);
CompareOperation compareOperation =
- new CompareOperation(conn, InternalClientConnection.nextOperationID(),
+ new CompareOperation(proxyUserConn,
+ InternalClientConnection.nextOperationID(),
InternalClientConnection.nextMessageID(),
controls,
new ASN1OctetString(entry.getDN().toString()),
@@ -490,16 +510,14 @@
{
InvocationCounterPlugin.resetAllCounters();
- InternalClientConnection conn =
- InternalClientConnection.getRootConnection();
-
ProxiedAuthV2Control authV2Control =
new ProxiedAuthV2Control(new ASN1OctetString("dn:"));
List<Control> controls = new ArrayList<Control>();
controls.add(authV2Control);
CompareOperation compareOperation =
- new CompareOperation(conn, InternalClientConnection.nextOperationID(),
+ new CompareOperation(proxyUserConn,
+ InternalClientConnection.nextOperationID(),
InternalClientConnection.nextMessageID(),
controls,
new ASN1OctetString(entry.getDN().toString()),
@@ -518,16 +536,14 @@
{
InvocationCounterPlugin.resetAllCounters();
- InternalClientConnection conn =
- InternalClientConnection.getRootConnection();
-
ProxiedAuthV2Control authV2Control = new ProxiedAuthV2Control(
new ASN1OctetString("dn:cn=nonexistent,o=test"));
List<Control> controls = new ArrayList<Control>();
controls.add(authV2Control);
CompareOperation compareOperation =
- new CompareOperation(conn, InternalClientConnection.nextOperationID(),
+ new CompareOperation(proxyUserConn,
+ InternalClientConnection.nextOperationID(),
InternalClientConnection.nextMessageID(),
controls,
new ASN1OctetString(entry.getDN().toString()),
@@ -545,9 +561,6 @@
{
InvocationCounterPlugin.resetAllCounters();
- InternalClientConnection conn =
- InternalClientConnection.getRootConnection();
-
ProxiedAuthV2Control authV2Control =
new ProxiedAuthV2Control(new ASN1OctetString());
authV2Control.setCritical(false);
@@ -555,7 +568,8 @@
controls.add(authV2Control);
CompareOperation compareOperation =
- new CompareOperation(conn, InternalClientConnection.nextOperationID(),
+ new CompareOperation(proxyUserConn,
+ InternalClientConnection.nextOperationID(),
InternalClientConnection.nextMessageID(),
controls,
new ASN1OctetString(entry.getDN().toString()),
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/core/TestModifyDNOperation.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/core/TestModifyDNOperation.java
index 3e53387..75ae817 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/core/TestModifyDNOperation.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/core/TestModifyDNOperation.java
@@ -56,6 +56,7 @@
{
private Entry entry;
+ private InternalClientConnection proxyUserConn;
@BeforeClass
public void setUp() throws Exception
@@ -132,6 +133,25 @@
entry.getOperationalAttributes());
assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS);
assertNotNull(DirectoryServer.getEntry(entry.getDN()));
+
+ // Add a user capable of using the proxied authorization control.
+ TestCaseUtils.addEntry(
+ "dn: uid=proxy.user,o=test",
+ "objectClass: top",
+ "objectClass: person",
+ "objectClass: organizationalPerson",
+ "objectClass: inetOrgPerson",
+ "uid: proxy.user",
+ "givenName: Proxy",
+ "sn: User",
+ "cn: Proxy User",
+ "userPassword: password",
+ "ds-privilege-name: proxied-auth");
+
+ Entry proxyUserEntry =
+ DirectoryServer.getEntry(DN.decode("uid=proxy.user,o=test"));
+ AuthenticationInfo authInfo = new AuthenticationInfo(proxyUserEntry, false);
+ proxyUserConn = new InternalClientConnection(authInfo);
}
/**
@@ -806,12 +826,9 @@
controls.add(authV1Control);
InvocationCounterPlugin.resetAllCounters();
- InternalClientConnection conn =
- InternalClientConnection.getRootConnection();
-
ModifyDNOperation modifyDNOperation =
- new ModifyDNOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
- controls,
+ new ModifyDNOperation(proxyUserConn, proxyUserConn.nextOperationID(),
+ proxyUserConn.nextMessageID(), controls,
new ASN1OctetString("uid=user.0,ou=People,dc=example,dc=com"),
new ASN1OctetString("uid=user.test0"), false,
null);
@@ -835,8 +852,8 @@
InvocationCounterPlugin.resetAllCounters();
modifyDNOperation =
- new ModifyDNOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
- controls,
+ new ModifyDNOperation(proxyUserConn, proxyUserConn.nextOperationID(),
+ proxyUserConn.nextMessageID(), controls,
new ASN1OctetString("uid=user.test0,ou=People,dc=example,dc=com"),
new ASN1OctetString("uid=user.0"), true,
null);
@@ -868,12 +885,9 @@
controls.add(authV1Control);
InvocationCounterPlugin.resetAllCounters();
- InternalClientConnection conn =
- InternalClientConnection.getRootConnection();
-
ModifyDNOperation modifyDNOperation =
- new ModifyDNOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
- controls,
+ new ModifyDNOperation(proxyUserConn, proxyUserConn.nextOperationID(),
+ proxyUserConn.nextMessageID(), controls,
DN.decode("uid=user.0,ou=People,dc=example,dc=com"),
RDN.decode("uid=user.test0"), false,
null);
@@ -897,7 +911,8 @@
InvocationCounterPlugin.resetAllCounters();
modifyDNOperation =
- new ModifyDNOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ new ModifyDNOperation(proxyUserConn, proxyUserConn.nextOperationID(),
+ proxyUserConn.nextMessageID(),
controls,
DN.decode("uid=user.test0,ou=People,dc=example,dc=com"),
RDN.decode("uid=user.0"), true,
@@ -930,12 +945,9 @@
controls.add(authV1Control);
InvocationCounterPlugin.resetAllCounters();
- InternalClientConnection conn =
- InternalClientConnection.getRootConnection();
-
ModifyDNOperation modifyDNOperation =
- new ModifyDNOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
- controls,
+ new ModifyDNOperation(proxyUserConn, proxyUserConn.nextOperationID(),
+ proxyUserConn.nextMessageID(), controls,
DN.decode("uid=user.0,ou=People,dc=example,dc=com"),
RDN.decode("uid=user.test0"), false,
null);
@@ -957,12 +969,9 @@
controls.add(authV2Control);
InvocationCounterPlugin.resetAllCounters();
- InternalClientConnection conn =
- InternalClientConnection.getRootConnection();
-
ModifyDNOperation modifyDNOperation =
- new ModifyDNOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
- controls,
+ new ModifyDNOperation(proxyUserConn, proxyUserConn.nextOperationID(),
+ proxyUserConn.nextMessageID(), controls,
DN.decode("uid=user.0,ou=People,dc=example,dc=com"),
RDN.decode("uid=user.test0"), false,
null);
@@ -986,8 +995,8 @@
InvocationCounterPlugin.resetAllCounters();
modifyDNOperation =
- new ModifyDNOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
- controls,
+ new ModifyDNOperation(proxyUserConn, proxyUserConn.nextOperationID(),
+ proxyUserConn.nextMessageID(), controls,
DN.decode("uid=user.test0,ou=People,dc=example,dc=com"),
RDN.decode("uid=user.0"), true,
null);
@@ -1019,12 +1028,9 @@
controls.add(authV2Control);
InvocationCounterPlugin.resetAllCounters();
- InternalClientConnection conn =
- InternalClientConnection.getRootConnection();
-
ModifyDNOperation modifyDNOperation =
- new ModifyDNOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
- controls,
+ new ModifyDNOperation(proxyUserConn, proxyUserConn.nextOperationID(),
+ proxyUserConn.nextMessageID(), controls,
DN.decode("uid=user.0,ou=People,dc=example,dc=com"),
RDN.decode("uid=user.test0"), false,
null);
@@ -1047,12 +1053,9 @@
controls.add(authV2Control);
InvocationCounterPlugin.resetAllCounters();
- InternalClientConnection conn =
- InternalClientConnection.getRootConnection();
-
ModifyDNOperation modifyDNOperation =
- new ModifyDNOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
- controls,
+ new ModifyDNOperation(proxyUserConn, proxyUserConn.nextOperationID(),
+ proxyUserConn.nextMessageID(), controls,
DN.decode("uid=user.0,ou=People,dc=example,dc=com"),
RDN.decode("uid=user.test0"), false,
null);
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/DigestMD5SASLMechanismHandlerTestCase.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/DigestMD5SASLMechanismHandlerTestCase.java
index 238624a..2693a70 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/DigestMD5SASLMechanismHandlerTestCase.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/DigestMD5SASLMechanismHandlerTestCase.java
@@ -22,7 +22,7 @@
* CDDL HEADER END
*
*
- * Portions Copyright 2006 Sun Microsystems, Inc.
+ * Portions Copyright 2006-2007 Sun Microsystems, Inc.
*/
package org.opends.server.extensions;
@@ -727,6 +727,50 @@
/**
+ * Performs a failed LDAP bind using DIGEST-MD5 using an empty authorization
+ * ID.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test()
+ public void testLDAPBindFailEmptyAuthzID()
+ throws Exception
+ {
+ TestCaseUtils.initializeTestBackend(true);
+ TestCaseUtils.addEntry(
+ "dn: uid=test.user,o=test",
+ "objectClass: top",
+ "objectClass: person",
+ "objectClass: organizationalPerson",
+ "objectClass: inetOrgPerson",
+ "uid: test.user",
+ "givenName: Test",
+ "sn: User",
+ "cn: Test User",
+ "userPassword: password",
+ "ds-privilege-name: proxied-auth",
+ "ds-pwp-password-policy-dn: cn=Clear UserPassword Policy," +
+ "cn=Password Policies,cn=config");
+
+ String[] args =
+ {
+ "-h", "127.0.0.1",
+ "-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
+ "-o", "mech=DIGEST-MD5",
+ "-o", "authid=dn:uid=test.user,o=test",
+ "-o", "authzid=",
+ "-o", "realm=o=test",
+ "-w", "password",
+ "-b", "",
+ "-s", "base",
+ "(objectClass=*)"
+ };
+ assertFalse(LDAPSearch.mainSearch(args, false, null, null) == 0);
+ }
+
+
+
+ /**
* Performs a failed LDAP bind using DIGEST-MD5 using the dn: form of the
* authentication ID with the root DN (which has a stored password that's not
* reversible).
@@ -811,6 +855,138 @@
/**
+ * Performs a failed LDAP bind using DIGEST-MD5 using an authorization ID that
+ * contains the DN of an entry that doesn't exist.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test()
+ public void testLDAPBindFailNonexistentAuthzDN()
+ throws Exception
+ {
+ TestCaseUtils.initializeTestBackend(true);
+ TestCaseUtils.addEntry(
+ "dn: uid=test.user,o=test",
+ "objectClass: top",
+ "objectClass: person",
+ "objectClass: organizationalPerson",
+ "objectClass: inetOrgPerson",
+ "uid: test.user",
+ "givenName: Test",
+ "sn: User",
+ "cn: Test User",
+ "userPassword: password",
+ "ds-privilege-name: proxied-auth",
+ "ds-pwp-password-policy-dn: cn=Clear UserPassword Policy," +
+ "cn=Password Policies,cn=config");
+
+ String[] args =
+ {
+ "-h", "127.0.0.1",
+ "-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
+ "-o", "mech=DIGEST-MD5",
+ "-o", "authid=dn:uid=test.user,o=test",
+ "-o", "authzid=dn:uid=nonexistent,o=test",
+ "-o", "realm=o=test",
+ "-w", "password",
+ "-b", "",
+ "-s", "base",
+ "(objectClass=*)"
+ };
+ assertFalse(LDAPSearch.mainSearch(args, false, null, null) == 0);
+ }
+
+
+
+ /**
+ * Performs a failed LDAP bind using DIGEST-MD5 using an authorization ID that
+ * contains a username for an entry that doesn't exist.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test()
+ public void testLDAPBindFailNonexistentAuthzUsername()
+ throws Exception
+ {
+ TestCaseUtils.initializeTestBackend(true);
+ TestCaseUtils.addEntry(
+ "dn: uid=test.user,o=test",
+ "objectClass: top",
+ "objectClass: person",
+ "objectClass: organizationalPerson",
+ "objectClass: inetOrgPerson",
+ "uid: test.user",
+ "givenName: Test",
+ "sn: User",
+ "cn: Test User",
+ "userPassword: password",
+ "ds-privilege-name: proxied-auth",
+ "ds-pwp-password-policy-dn: cn=Clear UserPassword Policy," +
+ "cn=Password Policies,cn=config");
+
+ String[] args =
+ {
+ "-h", "127.0.0.1",
+ "-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
+ "-o", "mech=DIGEST-MD5",
+ "-o", "authid=dn:uid=test.user,o=test",
+ "-o", "authzid=u:nonexistent",
+ "-o", "realm=o=test",
+ "-w", "password",
+ "-b", "",
+ "-s", "base",
+ "(objectClass=*)"
+ };
+ assertFalse(LDAPSearch.mainSearch(args, false, null, null) == 0);
+ }
+
+
+
+ /**
+ * Performs a failed LDAP bind using DIGEST-MD5 using an authorization ID that
+ * contains a malformed DN.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test()
+ public void testLDAPBindFailMalformedAuthzDN()
+ throws Exception
+ {
+ TestCaseUtils.initializeTestBackend(true);
+ TestCaseUtils.addEntry(
+ "dn: uid=test.user,o=test",
+ "objectClass: top",
+ "objectClass: person",
+ "objectClass: organizationalPerson",
+ "objectClass: inetOrgPerson",
+ "uid: test.user",
+ "givenName: Test",
+ "sn: User",
+ "cn: Test User",
+ "userPassword: password",
+ "ds-privilege-name: proxied-auth",
+ "ds-pwp-password-policy-dn: cn=Clear UserPassword Policy," +
+ "cn=Password Policies,cn=config");
+
+ String[] args =
+ {
+ "-h", "127.0.0.1",
+ "-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
+ "-o", "mech=DIGEST-MD5",
+ "-o", "authid=dn:uid=test.user,o=test",
+ "-o", "authzid=dn:malformed",
+ "-o", "realm=o=test",
+ "-w", "password",
+ "-b", "",
+ "-s", "base",
+ "(objectClass=*)"
+ };
+ assertFalse(LDAPSearch.mainSearch(args, false, null, null) == 0);
+ }
+
+
+
+ /**
* Verifies that the server will reject a DIGEST-MD5 bind in which the first
* message contains SASL credentials (which isn't allowed).
*
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/PlainSASLMechanismHandlerTestCase.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/PlainSASLMechanismHandlerTestCase.java
index 0b47b1f..eedbede 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/PlainSASLMechanismHandlerTestCase.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/PlainSASLMechanismHandlerTestCase.java
@@ -22,7 +22,7 @@
* CDDL HEADER END
*
*
- * Portions Copyright 2006 Sun Microsystems, Inc.
+ * Portions Copyright 2006-2007 Sun Microsystems, Inc.
*/
package org.opends.server.extensions;
@@ -516,5 +516,128 @@
saslCredentials);
assertEquals(bindOperation.getResultCode(), ResultCode.INVALID_CREDENTIALS);
}
+
+
+
+ /**
+ * Performs a failed LDAP bind using PLAIN with an authorization ID that
+ * contains the DN of an entry that doesn't exist.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test()
+ public void testLDAPBindFailNonexistentAuthzDN()
+ throws Exception
+ {
+ TestCaseUtils.initializeTestBackend(true);
+ TestCaseUtils.addEntry(
+ "dn: uid=test.user,o=test",
+ "objectClass: top",
+ "objectClass: person",
+ "objectClass: organizationalPerson",
+ "objectClass: inetOrgPerson",
+ "uid: test.user",
+ "givenName: Test",
+ "sn: User",
+ "cn: Test User",
+ "userPassword: password",
+ "ds-privilege-name: proxied-auth");
+
+ String[] args =
+ {
+ "-h", "127.0.0.1",
+ "-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
+ "-o", "mech=PLAIN",
+ "-o", "authid=dn:uid=test.user,o=test",
+ "-o", "authzid=dn:uid=nonexistent,o=test",
+ "-w", "password",
+ "-b", "",
+ "-s", "base",
+ "(objectClass=*)"
+ };
+ assertFalse(LDAPSearch.mainSearch(args, false, null, null) == 0);
+ }
+
+
+
+ /**
+ * Performs a failed LDAP bind using PLAIN with an authorization ID that
+ * contains a username for an entry that doesn't exist.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test()
+ public void testLDAPBindFailNonexistentAuthzUsername()
+ throws Exception
+ {
+ TestCaseUtils.initializeTestBackend(true);
+ TestCaseUtils.addEntry(
+ "dn: uid=test.user,o=test",
+ "objectClass: top",
+ "objectClass: person",
+ "objectClass: organizationalPerson",
+ "objectClass: inetOrgPerson",
+ "uid: test.user",
+ "givenName: Test",
+ "sn: User",
+ "cn: Test User",
+ "userPassword: password",
+ "ds-privilege-name: proxied-auth");
+
+ String[] args =
+ {
+ "-h", "127.0.0.1",
+ "-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
+ "-o", "mech=PLAIN",
+ "-o", "authid=dn:uid=test.user,o=test",
+ "-o", "authzid=u:nonexistent",
+ "-w", "password",
+ "-b", "",
+ "-s", "base",
+ "(objectClass=*)"
+ };
+ assertFalse(LDAPSearch.mainSearch(args, false, null, null) == 0);
+ }
+
+
+
+ /**
+ * Performs a failed LDAP bind using PLAIN with an authorization ID that
+ * contains a malformed DN.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test()
+ public void testLDAPBindFailMalformedAuthzDN()
+ throws Exception
+ {
+ TestCaseUtils.initializeTestBackend(true);
+ TestCaseUtils.addEntry(
+ "dn: uid=test.user,o=test",
+ "objectClass: top",
+ "objectClass: person",
+ "objectClass: organizationalPerson",
+ "objectClass: inetOrgPerson",
+ "uid: test.user",
+ "givenName: Test",
+ "sn: User",
+ "cn: Test User",
+ "userPassword: password",
+ "ds-privilege-name: proxied-auth");
+
+ String[] args =
+ {
+ "-h", "127.0.0.1",
+ "-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
+ "-o", "mech=PLAIN",
+ "-o", "authid=dn:uid=test.user,o=test",
+ "-o", "authzid=dn:malformed",
+ "-w", "password",
+ "-b", "",
+ "-s", "base",
+ "(objectClass=*)"
+ };
+ assertFalse(LDAPSearch.mainSearch(args, false, null, null) == 0);
+ }
}
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/types/PrivilegeTestCase.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/types/PrivilegeTestCase.java
index 2fbf660..6f89632 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/types/PrivilegeTestCase.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/types/PrivilegeTestCase.java
@@ -43,6 +43,8 @@
import org.opends.server.backends.task.Task;
import org.opends.server.backends.task.TaskBackend;
import org.opends.server.backends.task.TaskState;
+import org.opends.server.controls.ProxiedAuthV1Control;
+import org.opends.server.controls.ProxiedAuthV2Control;
import org.opends.server.core.AddOperation;
import org.opends.server.core.CompareOperation;
import org.opends.server.core.DeleteOperation;
@@ -50,10 +52,12 @@
import org.opends.server.core.ModifyOperation;
import org.opends.server.core.ModifyDNOperation;
import org.opends.server.core.SchemaConfigManager;
+import org.opends.server.protocols.asn1.ASN1OctetString;
import org.opends.server.protocols.internal.InternalClientConnection;
import org.opends.server.protocols.internal.InternalSearchOperation;
import org.opends.server.tools.LDAPModify;
import org.opends.server.tools.LDAPPasswordModify;
+import org.opends.server.tools.LDAPSearch;
import org.opends.server.types.Attribute;
import org.opends.server.types.AuthenticationInfo;
import org.opends.server.types.DN;
@@ -120,6 +124,7 @@
"cn: Unprivileged Root",
"givenName: Unprivileged",
"sn: Root",
+ "uid: unprivileged.root",
"userPassword: password",
"ds-privilege-name: -config-read",
"ds-privilege-name: -config-write",
@@ -130,6 +135,19 @@
"ds-privilege-name: -backend-backup",
"ds-privilege-name: -backend-restore",
"",
+ "dn: cn=Proxy Root,cn=Root DNs,cn=config",
+ "objectClass: top",
+ "objectClass: person",
+ "objectClass: organizationalPerson",
+ "objectClass: inetOrgPerson",
+ "objectClass: ds-cfg-root-dn",
+ "cn: Proxy Root",
+ "givenName: Proxy",
+ "sn: Root",
+ "uid: proxy.root",
+ "userPassword: password",
+ "ds-privilege-name: proxied-auth",
+ "",
"dn: cn=Privileged User,o=test",
"objectClass: top",
"objectClass: person",
@@ -138,6 +156,7 @@
"cn: Privileged User",
"givenName: Privileged",
"sn: User",
+ "uid: privileged.user",
"userPassword: password",
"ds-privilege-name: config-read",
"ds-privilege-name: config-write",
@@ -147,6 +166,9 @@
"ds-privilege-name: ldif-export",
"ds-privilege-name: backend-backup",
"ds-privilege-name: backend-restore",
+ "ds-privilege-name: proxied-auth",
+ "ds-pwp-password-policy-dn: cn=Clear UserPassword Policy," +
+ "cn=Password Policies,cn=config",
"",
"dn: cn=Unprivileged User,o=test",
"objectClass: top",
@@ -156,7 +178,10 @@
"cn: Unprivileged User",
"givenName: Unprivileged",
"sn: User",
+ "uid: unprivileged.user",
"userPassword: password",
+ "ds-pwp-password-policy-dn: cn=Clear UserPassword Policy," +
+ "cn=Password Policies,cn=config",
"",
"dn: cn=PWReset Target,o=test",
"objectClass: top",
@@ -166,6 +191,7 @@
"cn: PWReset Target",
"givenName: PWReset",
"sn: Target",
+ "uid: pwreset.target",
"userPassword: password");
// FIXME -- It will likely be necessary to also have access control rules in
@@ -196,6 +222,12 @@
connList.add(new InternalClientConnection(authInfo));
successList.add(false);
+ userDN = "cn=Proxy Root,cn=Root DNs,cn=config";
+ userEntry = DirectoryServer.getEntry(DN.decode(userDN));
+ authInfo = new AuthenticationInfo(userEntry, true);
+ connList.add(new InternalClientConnection(authInfo));
+ successList.add(true);
+
userDN = "cn=Unprivileged User,o=test";
userEntry = DirectoryServer.getEntry(DN.decode(userDN));
authInfo = new AuthenticationInfo(userEntry, false);
@@ -985,6 +1017,1129 @@
/**
+ * Tests to ensure that the use of the Directory Server will properly respect
+ * the PROXIED_AUTH privilege for add, delete, modify and modify DN requests
+ * that contain the proxied auth v1 control.
+ *
+ * @param conn The client connection to use to perform the
+ * operation.
+ * @param hasPrivilege Indicates whether the authenticated user is expected
+ * to have the PROXIED_AUTH privilege and therefore
+ * the operation should succeed.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test(dataProvider = "testdata")
+ public void testProxyAuthV1Write(InternalClientConnection conn,
+ boolean hasPrivilege)
+ throws Exception
+ {
+ // We can't trust the value of hasPrivilege because root users don't get
+ // proxy privileges by default. So make the determination based on the
+ // privileges the user actually has.
+ boolean hasProxyPrivilege = conn.hasPrivilege(Privilege.PROXIED_AUTH, null);
+
+ Entry e = TestCaseUtils.makeEntry(
+ "dn: cn=ProxyV1 Test,o=test",
+ "objectClass: top",
+ "objectClass: person",
+ "objectClass: organizationalPerson",
+ "objectClass: inetOrgPerson",
+ "cn: ProxyV1 Test",
+ "givenName: ProxyV1",
+ "sn: Test");
+
+ ArrayList<Control> controls = new ArrayList<Control>(1);
+ controls.add(new ProxiedAuthV1Control(
+ DN.decode("cn=PWReset Target,o=test")));
+
+
+ // Try to add the entry. If this fails with the proxy control, then add it
+ // with a root connection so we can do other things with it.
+ AddOperation addOperation =
+ new AddOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ controls, e.getDN(), e.getObjectClasses(),
+ e.getUserAttributes(), e.getOperationalAttributes());
+ addOperation.run();
+
+ if (hasProxyPrivilege)
+ {
+ assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS);
+ }
+ else
+ {
+ assertEquals(addOperation.getResultCode(),
+ ResultCode.AUTHORIZATION_DENIED);
+ TestCaseUtils.addEntry(e);
+ }
+
+
+ // Try to modify the entry to add a description.
+ ArrayList<Modification> mods = new ArrayList<Modification>(1);
+ mods.add(new Modification(ModificationType.REPLACE,
+ new Attribute("description", "foo")));
+
+ ModifyOperation modifyOperation =
+ new ModifyOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ controls, e.getDN(), mods);
+ modifyOperation.run();
+
+ if (hasProxyPrivilege)
+ {
+ assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS);
+ }
+ else
+ {
+ assertEquals(modifyOperation.getResultCode(),
+ ResultCode.AUTHORIZATION_DENIED);
+ }
+
+
+ // Try to rename the entry.
+ ModifyDNOperation modifyDNOperation =
+ new ModifyDNOperation(conn, conn.nextOperationID(),
+ conn.nextMessageID(), controls, e.getDN(),
+ RDN.decode("cn=Proxy V1 Test"), true, null);
+ modifyDNOperation.run();
+
+ DN newEntryDN;
+ if (hasProxyPrivilege)
+ {
+ assertEquals(modifyDNOperation.getResultCode(), ResultCode.SUCCESS);
+ newEntryDN = modifyDNOperation.getUpdatedEntry().getDN();
+ }
+ else
+ {
+ assertEquals(modifyDNOperation.getResultCode(),
+ ResultCode.AUTHORIZATION_DENIED);
+ newEntryDN = e.getDN();
+ }
+
+
+ // Try to delete the operation. If this fails, then delete it with a root
+ // connection so it gets cleaned up.
+ DeleteOperation deleteOperation =
+ new DeleteOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ controls, newEntryDN);
+ deleteOperation.run();
+
+ if (hasProxyPrivilege)
+ {
+ assertEquals(deleteOperation.getResultCode(), ResultCode.SUCCESS);
+ }
+ else
+ {
+ assertEquals(deleteOperation.getResultCode(),
+ ResultCode.AUTHORIZATION_DENIED);
+
+ InternalClientConnection rootConnection =
+ InternalClientConnection.getRootConnection();
+ deleteOperation = rootConnection.processDelete(newEntryDN);
+ assertEquals(deleteOperation.getResultCode(), ResultCode.SUCCESS);
+ }
+ }
+
+
+
+ /**
+ * Tests to ensure that the use of the Directory Server will properly respect
+ * the PROXIED_AUTH privilege for search and compare requests that contain the
+ * proxied auth v1 control.
+ *
+ * @param conn The client connection to use to perform the
+ * operation.
+ * @param hasPrivilege Indicates whether the authenticated user is expected
+ * to have the PROXIED_AUTH privilege and therefore
+ * the operation should succeed.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test(dataProvider = "testdata")
+ public void testProxyAuthV1Read(InternalClientConnection conn,
+ boolean hasPrivilege)
+ throws Exception
+ {
+ // We can't trust the value of hasPrivilege because root users don't get
+ // proxy privileges by default. So make the determination based on the
+ // privileges the user actually has.
+ boolean hasProxyPrivilege = conn.hasPrivilege(Privilege.PROXIED_AUTH, null);
+
+ DN targetDN = DN.decode("cn=PWReset Target,o=test");
+ ArrayList<Control> controls = new ArrayList<Control>(1);
+ controls.add(new ProxiedAuthV1Control(targetDN));
+
+
+ // Test a compare operation against the PWReset Target user.
+ CompareOperation compareOperation =
+ new CompareOperation(conn, conn.nextOperationID(),
+ conn.nextMessageID(), controls, targetDN,
+ DirectoryServer.getAttributeType("cn", true),
+ ByteStringFactory.create("PWReset Target"));
+ compareOperation.run();
+
+ if (hasProxyPrivilege)
+ {
+ assertEquals(compareOperation.getResultCode(), ResultCode.COMPARE_TRUE);
+ }
+ else
+ {
+ assertEquals(compareOperation.getResultCode(),
+ ResultCode.AUTHORIZATION_DENIED);
+ }
+
+
+ // Test a search operation against the PWReset Target user.
+ InternalSearchOperation searchOperation =
+ new InternalSearchOperation(conn, conn.nextOperationID(),
+ conn.nextMessageID(), controls, targetDN,
+ SearchScope.BASE_OBJECT,
+ DereferencePolicy.NEVER_DEREF_ALIASES, 0, 0, false,
+ SearchFilter.createFilterFromString("(objectClass=*)"), null,
+ null);
+ searchOperation.run();
+
+ if (hasProxyPrivilege)
+ {
+ assertEquals(searchOperation.getResultCode(), ResultCode.SUCCESS);
+ }
+ else
+ {
+ assertEquals(searchOperation.getResultCode(),
+ ResultCode.AUTHORIZATION_DENIED);
+ }
+ }
+
+
+
+ /**
+ * Tests to ensure that the use of the Directory Server will properly respect
+ * the PROXIED_AUTH privilege for add, delete, modify and modify DN requests
+ * that contain the proxied auth v2 control.
+ *
+ * @param conn The client connection to use to perform the
+ * operation.
+ * @param hasPrivilege Indicates whether the authenticated user is expected
+ * to have the PROXIED_AUTH privilege and therefore
+ * the operation should succeed.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test(dataProvider = "testdata")
+ public void testProxyAuthV2Write(InternalClientConnection conn,
+ boolean hasPrivilege)
+ throws Exception
+ {
+ // We can't trust the value of hasPrivilege because root users don't get
+ // proxy privileges by default. So make the determination based on the
+ // privileges the user actually has.
+ boolean hasProxyPrivilege = conn.hasPrivilege(Privilege.PROXIED_AUTH, null);
+
+ Entry e = TestCaseUtils.makeEntry(
+ "dn: cn=ProxyV2 Test,o=test",
+ "objectClass: top",
+ "objectClass: person",
+ "objectClass: organizationalPerson",
+ "objectClass: inetOrgPerson",
+ "cn: ProxyV2 Test",
+ "givenName: ProxyV2",
+ "sn: Test");
+
+ ArrayList<Control> controls = new ArrayList<Control>(1);
+ controls.add(new ProxiedAuthV2Control(
+ new ASN1OctetString("dn:cn=PWReset Target,o=test")));
+
+
+ // Try to add the entry. If this fails with the proxy control, then add it
+ // with a root connection so we can do other things with it.
+ AddOperation addOperation =
+ new AddOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ controls, e.getDN(), e.getObjectClasses(),
+ e.getUserAttributes(), e.getOperationalAttributes());
+ addOperation.run();
+
+ if (hasProxyPrivilege)
+ {
+ assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS);
+ }
+ else
+ {
+ assertEquals(addOperation.getResultCode(),
+ ResultCode.AUTHORIZATION_DENIED);
+ TestCaseUtils.addEntry(e);
+ }
+
+
+ // Try to modify the entry to add a description.
+ ArrayList<Modification> mods = new ArrayList<Modification>(1);
+ mods.add(new Modification(ModificationType.REPLACE,
+ new Attribute("description", "foo")));
+
+ ModifyOperation modifyOperation =
+ new ModifyOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ controls, e.getDN(), mods);
+ modifyOperation.run();
+
+ if (hasProxyPrivilege)
+ {
+ assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS);
+ }
+ else
+ {
+ assertEquals(modifyOperation.getResultCode(),
+ ResultCode.AUTHORIZATION_DENIED);
+ }
+
+
+ // Try to rename the entry.
+ ModifyDNOperation modifyDNOperation =
+ new ModifyDNOperation(conn, conn.nextOperationID(),
+ conn.nextMessageID(), controls, e.getDN(),
+ RDN.decode("cn=Proxy V2 Test"), true, null);
+ modifyDNOperation.run();
+
+ DN newEntryDN;
+ if (hasProxyPrivilege)
+ {
+ assertEquals(modifyDNOperation.getResultCode(), ResultCode.SUCCESS);
+ newEntryDN = modifyDNOperation.getUpdatedEntry().getDN();
+ }
+ else
+ {
+ assertEquals(modifyDNOperation.getResultCode(),
+ ResultCode.AUTHORIZATION_DENIED);
+ newEntryDN = e.getDN();
+ }
+
+
+ // Try to delete the operation. If this fails, then delete it with a root
+ // connection so it gets cleaned up.
+ DeleteOperation deleteOperation =
+ new DeleteOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ controls, newEntryDN);
+ deleteOperation.run();
+
+ if (hasProxyPrivilege)
+ {
+ assertEquals(deleteOperation.getResultCode(), ResultCode.SUCCESS);
+ }
+ else
+ {
+ assertEquals(deleteOperation.getResultCode(),
+ ResultCode.AUTHORIZATION_DENIED);
+
+ InternalClientConnection rootConnection =
+ InternalClientConnection.getRootConnection();
+ deleteOperation = rootConnection.processDelete(newEntryDN);
+ assertEquals(deleteOperation.getResultCode(), ResultCode.SUCCESS);
+ }
+ }
+
+
+
+ /**
+ * Tests to ensure that the use of the Directory Server will properly respect
+ * the PROXIED_AUTH privilege for search and compare requests that contain the
+ * proxied auth v2 control.
+ *
+ * @param conn The client connection to use to perform the
+ * operation.
+ * @param hasPrivilege Indicates whether the authenticated user is expected
+ * to have the PROXIED_AUTH privilege and therefore
+ * the operation should succeed.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test(dataProvider = "testdata")
+ public void testProxyAuthV2Read(InternalClientConnection conn,
+ boolean hasPrivilege)
+ throws Exception
+ {
+ // We can't trust the value of hasPrivilege because root users don't get
+ // proxy privileges by default. So make the determination based on the
+ // privileges the user actually has.
+ boolean hasProxyPrivilege = conn.hasPrivilege(Privilege.PROXIED_AUTH, null);
+
+ DN targetDN = DN.decode("cn=PWReset Target,o=test");
+ ArrayList<Control> controls = new ArrayList<Control>(1);
+ controls.add(new ProxiedAuthV2Control(
+ new ASN1OctetString("dn:" + targetDN.toString())));
+
+
+ // Test a compare operation against the PWReset Target user.
+ CompareOperation compareOperation =
+ new CompareOperation(conn, conn.nextOperationID(),
+ conn.nextMessageID(), controls, targetDN,
+ DirectoryServer.getAttributeType("cn", true),
+ ByteStringFactory.create("PWReset Target"));
+ compareOperation.run();
+
+ if (hasProxyPrivilege)
+ {
+ assertEquals(compareOperation.getResultCode(), ResultCode.COMPARE_TRUE);
+ }
+ else
+ {
+ assertEquals(compareOperation.getResultCode(),
+ ResultCode.AUTHORIZATION_DENIED);
+ }
+
+
+ // Test a search operation against the PWReset Target user.
+ InternalSearchOperation searchOperation =
+ new InternalSearchOperation(conn, conn.nextOperationID(),
+ conn.nextMessageID(), controls, targetDN,
+ SearchScope.BASE_OBJECT,
+ DereferencePolicy.NEVER_DEREF_ALIASES, 0, 0, false,
+ SearchFilter.createFilterFromString("(objectClass=*)"), null,
+ null);
+ searchOperation.run();
+
+ if (hasProxyPrivilege)
+ {
+ assertEquals(searchOperation.getResultCode(), ResultCode.SUCCESS);
+ }
+ else
+ {
+ assertEquals(searchOperation.getResultCode(),
+ ResultCode.AUTHORIZATION_DENIED);
+ }
+ }
+
+
+
+ /**
+ * Tests to ensure that the server will properly respect the PROXIED_AUTH
+ * privilege when attempting to perform DIGEST-MD5 authentication when an
+ * anonymous authorization ID is specified with an authentication identity
+ * that has sufficient privileges and using the "dn:" syntax.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test()
+ public void testDIGESTMD5AnonymousAuthzIDSuccessfulDNColon()
+ throws Exception
+ {
+ String[] args =
+ {
+ "-h", "127.0.0.1",
+ "-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
+ "-o", "mech=DIGEST-MD5",
+ "-o", "authid=dn:cn=Privileged User,o=test",
+ "-o", "authzid=dn:",
+ "-o", "realm=o=test",
+ "-w", "password",
+ "-b", "o=test",
+ "-s", "base",
+ "(objectClass=*)"
+ };
+
+ assertEquals(LDAPSearch.mainSearch(args, false, null, System.err), 0);
+ }
+
+
+
+ /**
+ * Tests to ensure that the server will behave properly when attempting to
+ * perform DIGEST-MD5 authentication when an authorization ID equaling the
+ * authentication ID is specified with an authentication identity that has
+ * sufficient privileges and using the "dn:" syntax.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test()
+ public void testDIGESTMD5SameAuthzIDSuccessfulDNColon()
+ throws Exception
+ {
+ String[] args =
+ {
+ "-h", "127.0.0.1",
+ "-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
+ "-o", "mech=DIGEST-MD5",
+ "-o", "authid=dn:cn=Privileged User,o=test",
+ "-o", "authzid=dn:cn=Privileged User,o=test",
+ "-o", "realm=o=test",
+ "-w", "password",
+ "-b", "o=test",
+ "-s", "base",
+ "(objectClass=*)"
+ };
+
+ assertEquals(LDAPSearch.mainSearch(args, false, null, System.err), 0);
+ }
+
+
+
+ /**
+ * Tests to ensure that the server will properly respect the PROXIED_AUTH
+ * privilege when attempting to perform DIGEST-MD5 authentication when an
+ * alternate authorization ID is specified with an authentication identity
+ * that has sufficient privileges and using the "dn:" syntax.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test()
+ public void testDIGESTMD5DifferentAuthzIDSuccessfulDNColon()
+ throws Exception
+ {
+ String[] args =
+ {
+ "-h", "127.0.0.1",
+ "-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
+ "-o", "mech=DIGEST-MD5",
+ "-o", "authid=dn:cn=Privileged User,o=test",
+ "-o", "authzid=dn:cn=Unprivileged User,o=test",
+ "-o", "realm=o=test",
+ "-w", "password",
+ "-b", "o=test",
+ "-s", "base",
+ "(objectClass=*)"
+ };
+
+ assertEquals(LDAPSearch.mainSearch(args, false, null, System.err), 0);
+ }
+
+
+
+ /**
+ * Tests to ensure that the server will properly respect the PROXIED_AUTH
+ * privilege when attempting to perform DIGEST-MD5 authentication when an
+ * anonymous authorization ID is specified with an authentication identity
+ * that has sufficient privileges and using the "u:" syntax.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test()
+ public void testDIGESTMD5AnonymousAuthzIDSuccessfulUColon()
+ throws Exception
+ {
+ String[] args =
+ {
+ "-h", "127.0.0.1",
+ "-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
+ "-o", "mech=DIGEST-MD5",
+ "-o", "authid=u:privileged.user",
+ "-o", "authzid=u:",
+ "-o", "realm=o=test",
+ "-w", "password",
+ "-b", "o=test",
+ "-s", "base",
+ "(objectClass=*)"
+ };
+
+ assertEquals(LDAPSearch.mainSearch(args, false, null, System.err), 0);
+ }
+
+
+
+ /**
+ * Tests to ensure that the server will behave properly when attempting to
+ * perform DIGEST-MD5 authentication when an authorization ID equaling the
+ * authentication ID is specified with an authentication identity that has
+ * sufficient privileges and using the "u:" syntax.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test()
+ public void testDIGESTMD5SameAuthzIDSuccessfulUColon()
+ throws Exception
+ {
+ String[] args =
+ {
+ "-h", "127.0.0.1",
+ "-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
+ "-o", "mech=DIGEST-MD5",
+ "-o", "authid=u:privileged.user",
+ "-o", "authzid=u:privileged.user",
+ "-o", "realm=o=test",
+ "-w", "password",
+ "-b", "o=test",
+ "-s", "base",
+ "(objectClass=*)"
+ };
+
+ assertEquals(LDAPSearch.mainSearch(args, false, null, System.err), 0);
+ }
+
+
+
+ /**
+ * Tests to ensure that the server will properly respect the PROXIED_AUTH
+ * privilege when attempting to perform DIGEST-MD5 authentication when an
+ * alternate authorization ID is specified with an authentication identity
+ * that has sufficient privileges and using the "u:" syntax.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test()
+ public void testDIGESTMD5DifferentAuthzIDSuccessfulUColon()
+ throws Exception
+ {
+ String[] args =
+ {
+ "-h", "127.0.0.1",
+ "-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
+ "-o", "mech=DIGEST-MD5",
+ "-o", "authid=u:privileged.user",
+ "-o", "authzid=u:unprivileged.user",
+ "-o", "realm=o=test",
+ "-w", "password",
+ "-b", "o=test",
+ "-s", "base",
+ "(objectClass=*)"
+ };
+
+ assertEquals(LDAPSearch.mainSearch(args, false, null, System.err), 0);
+ }
+
+
+
+ /**
+ * Tests to ensure that the server will properly respect the PROXIED_AUTH
+ * privilege when attempting to perform DIGEST-MD5 authentication when an
+ * anonymous authorization ID is specified with an authentication identity
+ * that does not have sufficient privileges and using the "dn:" syntax.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test()
+ public void testDIGESTMD5AnonymousAuthzIDFailedDNColon()
+ throws Exception
+ {
+ String[] args =
+ {
+ "-h", "127.0.0.1",
+ "-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
+ "-o", "mech=DIGEST-MD5",
+ "-o", "authid=dn:cn=Unprivileged User,o=test",
+ "-o", "authzid=dn:",
+ "-o", "realm=o=test",
+ "-w", "password",
+ "-b", "o=test",
+ "-s", "base",
+ "(objectClass=*)"
+ };
+
+ assertFalse(LDAPSearch.mainSearch(args, false, null, null) == 0);
+ }
+
+
+
+ /**
+ * Tests to ensure that the server will behave properly when attempting to
+ * perform DIGEST-MD5 authentication when an authorization ID equaling the
+ * authentication ID is specified with an authentication identity that does
+ * not have sufficient privileges and using the "dn:" syntax.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test()
+ public void testDIGESTMD5SameUnprivAuthzIDSuccessfulDNColon()
+ throws Exception
+ {
+ String[] args =
+ {
+ "-h", "127.0.0.1",
+ "-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
+ "-o", "mech=DIGEST-MD5",
+ "-o", "authid=dn:cn=Unprivileged User,o=test",
+ "-o", "authzid=dn:cn=Unprivileged User,o=test",
+ "-o", "realm=o=test",
+ "-w", "password",
+ "-b", "o=test",
+ "-s", "base",
+ "(objectClass=*)"
+ };
+
+ assertEquals(LDAPSearch.mainSearch(args, false, null, System.err), 0);
+ }
+
+
+
+ /**
+ * Tests to ensure that the server will properly respect the PROXIED_AUTH
+ * privilege when attempting to perform DIGEST-MD5 authentication when an
+ * alternate authorization ID is specified with an authentication identity
+ * that does not have sufficient privileges and using the "dn:" syntax.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test()
+ public void testDIGESTMD5DifferentAuthzIDFailedDNColon()
+ throws Exception
+ {
+ String[] args =
+ {
+ "-h", "127.0.0.1",
+ "-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
+ "-o", "mech=DIGEST-MD5",
+ "-o", "authid=dn:cn=Unprivileged User,o=test",
+ "-o", "authzid=dn:cn=Privileged User,o=test",
+ "-o", "realm=o=test",
+ "-w", "password",
+ "-b", "o=test",
+ "-s", "base",
+ "(objectClass=*)"
+ };
+
+ assertFalse(LDAPSearch.mainSearch(args, false, null, null) == 0);
+ }
+
+
+
+ /**
+ * Tests to ensure that the server will properly respect the PROXIED_AUTH
+ * privilege when attempting to perform DIGEST-MD5 authentication when an
+ * anonymous authorization ID is specified with an authentication identity
+ * that does not have sufficient privileges and using the "u:" syntax.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test()
+ public void testDIGESTMD5AnonymousAuthzIDFailedUColon()
+ throws Exception
+ {
+ String[] args =
+ {
+ "-h", "127.0.0.1",
+ "-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
+ "-o", "mech=DIGEST-MD5",
+ "-o", "authid=u:unprivileged.user",
+ "-o", "authzid=u:",
+ "-o", "realm=o=test",
+ "-w", "password",
+ "-b", "o=test",
+ "-s", "base",
+ "(objectClass=*)"
+ };
+
+ assertFalse(LDAPSearch.mainSearch(args, false, null, null) == 0);
+ }
+
+
+
+ /**
+ * Tests to ensure that the server will behave properly when attempting to
+ * perform DIGEST-MD5 authentication when an authorization ID equaling the
+ * authentication ID is specified with an authentication identity that does
+ * not have sufficient privileges and using the "u:" syntax.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test()
+ public void testDIGESTMD5SameUnprivAuthzIDSuccessfulUColon()
+ throws Exception
+ {
+ String[] args =
+ {
+ "-h", "127.0.0.1",
+ "-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
+ "-o", "mech=DIGEST-MD5",
+ "-o", "authid=u:unprivileged.user",
+ "-o", "authzid=u:unprivileged.user",
+ "-o", "realm=o=test",
+ "-w", "password",
+ "-b", "o=test",
+ "-s", "base",
+ "(objectClass=*)"
+ };
+
+ assertEquals(LDAPSearch.mainSearch(args, false, null, System.err), 0);
+ }
+
+
+
+ /**
+ * Tests to ensure that the server will properly respect the PROXIED_AUTH
+ * privilege when attempting to perform DIGEST-MD5 authentication when an
+ * alternate authorization ID is specified with an authentication identity
+ * that does not have sufficient privileges and using the "u:" syntax.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test()
+ public void testDIGESTMD5DifferentAuthzIDFailedUColon()
+ throws Exception
+ {
+ String[] args =
+ {
+ "-h", "127.0.0.1",
+ "-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
+ "-o", "mech=DIGEST-MD5",
+ "-o", "authid=u:unprivileged.user",
+ "-o", "authzid=u:privileged.user",
+ "-o", "realm=o=test",
+ "-w", "password",
+ "-b", "o=test",
+ "-s", "base",
+ "(objectClass=*)"
+ };
+
+ assertFalse(LDAPSearch.mainSearch(args, false, null, null) == 0);
+ }
+
+
+
+ /**
+ * Tests to ensure that the server will properly respect the PROXIED_AUTH
+ * privilege when attempting to perform PLAIN authentication when an
+ * anonymous authorization ID is specified with an authentication identity
+ * that has sufficient privileges and using the "dn:" syntax.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test()
+ public void testPLAINAnonymousAuthzIDSuccessfulDNColon()
+ throws Exception
+ {
+ String[] args =
+ {
+ "-h", "127.0.0.1",
+ "-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
+ "-o", "mech=PLAIN",
+ "-o", "authid=dn:cn=Privileged User,o=test",
+ "-o", "authzid=dn:",
+ "-w", "password",
+ "-b", "o=test",
+ "-s", "base",
+ "(objectClass=*)"
+ };
+
+ assertEquals(LDAPSearch.mainSearch(args, false, null, System.err), 0);
+ }
+
+
+
+ /**
+ * Tests to ensure that the server will behave properly when attempting to
+ * perform PLAIN authentication when an authorization ID equaling the
+ * authentication ID is specified with an authentication identity that has
+ * sufficient privileges and using the "dn:" syntax.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test()
+ public void testPLAINSameAuthzIDSuccessfulDNColon()
+ throws Exception
+ {
+ String[] args =
+ {
+ "-h", "127.0.0.1",
+ "-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
+ "-o", "mech=PLAIN",
+ "-o", "authid=dn:cn=Privileged User,o=test",
+ "-o", "authzid=dn:cn=Privileged User,o=test",
+ "-w", "password",
+ "-b", "o=test",
+ "-s", "base",
+ "(objectClass=*)"
+ };
+
+ assertEquals(LDAPSearch.mainSearch(args, false, null, System.err), 0);
+ }
+
+
+
+ /**
+ * Tests to ensure that the server will properly respect the PROXIED_AUTH
+ * privilege when attempting to perform PLAIN authentication when an
+ * alternate authorization ID is specified with an authentication identity
+ * that has sufficient privileges and using the "dn:" syntax.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test()
+ public void testPLAINDifferentAuthzIDSuccessfulDNColon()
+ throws Exception
+ {
+ String[] args =
+ {
+ "-h", "127.0.0.1",
+ "-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
+ "-o", "mech=PLAIN",
+ "-o", "authid=dn:cn=Privileged User,o=test",
+ "-o", "authzid=dn:cn=Unprivileged User,o=test",
+ "-w", "password",
+ "-b", "o=test",
+ "-s", "base",
+ "(objectClass=*)"
+ };
+
+ assertEquals(LDAPSearch.mainSearch(args, false, null, System.err), 0);
+ }
+
+
+
+ /**
+ * Tests to ensure that the server will properly respect the PROXIED_AUTH
+ * privilege when attempting to perform PLAIN authentication when an
+ * anonymous authorization ID is specified with an authentication identity
+ * that has sufficient privileges and using the "u:" syntax.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test()
+ public void testPLAINAnonymousAuthzIDSuccessfulUColon()
+ throws Exception
+ {
+ String[] args =
+ {
+ "-h", "127.0.0.1",
+ "-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
+ "-o", "mech=PLAIN",
+ "-o", "authid=u:privileged.user",
+ "-o", "authzid=u:",
+ "-w", "password",
+ "-b", "o=test",
+ "-s", "base",
+ "(objectClass=*)"
+ };
+
+ assertEquals(LDAPSearch.mainSearch(args, false, null, System.err), 0);
+ }
+
+
+
+ /**
+ * Tests to ensure that the server will behave properly when attempting to
+ * perform PLAIN authentication when an authorization ID equaling the
+ * authentication ID is specified with an authentication identity that has
+ * sufficient privileges and using the "u:" syntax.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test()
+ public void testPLAINSameAuthzIDSuccessfulUColon()
+ throws Exception
+ {
+ String[] args =
+ {
+ "-h", "127.0.0.1",
+ "-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
+ "-o", "mech=PLAIN",
+ "-o", "authid=u:privileged.user",
+ "-o", "authzid=u:privileged.user",
+ "-w", "password",
+ "-b", "o=test",
+ "-s", "base",
+ "(objectClass=*)"
+ };
+
+ assertEquals(LDAPSearch.mainSearch(args, false, null, System.err), 0);
+ }
+
+
+
+ /**
+ * Tests to ensure that the server will properly respect the PROXIED_AUTH
+ * privilege when attempting to perform PLAIN authentication when an
+ * alternate authorization ID is specified with an authentication identity
+ * that has sufficient privileges and using the "u:" syntax.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test()
+ public void testPLAINDifferentAuthzIDSuccessfulUColon()
+ throws Exception
+ {
+ String[] args =
+ {
+ "-h", "127.0.0.1",
+ "-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
+ "-o", "mech=PLAIN",
+ "-o", "authid=u:privileged.user",
+ "-o", "authzid=u:unprivileged.user",
+ "-w", "password",
+ "-b", "o=test",
+ "-s", "base",
+ "(objectClass=*)"
+ };
+
+ assertEquals(LDAPSearch.mainSearch(args, false, null, System.err), 0);
+ }
+
+
+
+ /**
+ * Tests to ensure that the server will properly respect the PROXIED_AUTH
+ * privilege when attempting to perform PLAIN authentication when an
+ * anonymous authorization ID is specified with an authentication identity
+ * that does not have sufficient privileges and using the "dn:" syntax.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test()
+ public void testPLAINAnonymousAuthzIDFailedDNColon()
+ throws Exception
+ {
+ String[] args =
+ {
+ "-h", "127.0.0.1",
+ "-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
+ "-o", "mech=PLAIN",
+ "-o", "authid=dn:cn=Unprivileged User,o=test",
+ "-o", "authzid=dn:",
+ "-w", "password",
+ "-b", "o=test",
+ "-s", "base",
+ "(objectClass=*)"
+ };
+
+ assertFalse(LDAPSearch.mainSearch(args, false, null, null) == 0);
+ }
+
+
+
+ /**
+ * Tests to ensure that the server will behave properly when attempting to
+ * perform PLAIN authentication when an authorization ID equaling the
+ * authentication ID is specified with an authentication identity that does
+ * not have sufficient privileges and using the "dn:" syntax.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test()
+ public void testPLAINSameUnprivAuthzIDSuccessfulDNColon()
+ throws Exception
+ {
+ String[] args =
+ {
+ "-h", "127.0.0.1",
+ "-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
+ "-o", "mech=PLAIN",
+ "-o", "authid=dn:cn=Unprivileged User,o=test",
+ "-o", "authzid=dn:cn=Unprivileged User,o=test",
+ "-w", "password",
+ "-b", "o=test",
+ "-s", "base",
+ "(objectClass=*)"
+ };
+
+ assertEquals(LDAPSearch.mainSearch(args, false, null, System.err), 0);
+ }
+
+
+
+ /**
+ * Tests to ensure that the server will properly respect the PROXIED_AUTH
+ * privilege when attempting to perform PLAIN authentication when an
+ * alternate authorization ID is specified with an authentication identity
+ * that does not have sufficient privileges and using the "dn:" syntax.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test()
+ public void testPLAINDifferentAuthzIDFailedDNColon()
+ throws Exception
+ {
+ String[] args =
+ {
+ "-h", "127.0.0.1",
+ "-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
+ "-o", "mech=PLAIN",
+ "-o", "authid=dn:cn=Unprivileged User,o=test",
+ "-o", "authzid=dn:cn=Privileged User,o=test",
+ "-w", "password",
+ "-b", "o=test",
+ "-s", "base",
+ "(objectClass=*)"
+ };
+
+ assertFalse(LDAPSearch.mainSearch(args, false, null, null) == 0);
+ }
+
+
+
+ /**
+ * Tests to ensure that the server will properly respect the PROXIED_AUTH
+ * privilege when attempting to perform PLAIN authentication when an
+ * anonymous authorization ID is specified with an authentication identity
+ * that does not have sufficient privileges and using the "u:" syntax.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test()
+ public void testPLAINAnonymousAuthzIDFailedUColon()
+ throws Exception
+ {
+ String[] args =
+ {
+ "-h", "127.0.0.1",
+ "-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
+ "-o", "mech=PLAIN",
+ "-o", "authid=u:unprivileged.user",
+ "-o", "authzid=u:",
+ "-w", "password",
+ "-b", "o=test",
+ "-s", "base",
+ "(objectClass=*)"
+ };
+
+ assertFalse(LDAPSearch.mainSearch(args, false, null, null) == 0);
+ }
+
+
+
+ /**
+ * Tests to ensure that the server will behave properly when attempting to
+ * perform PLAIN authentication when an authorization ID equaling the
+ * authentication ID is specified with an authentication identity that does
+ * not have sufficient privileges and using the "u:" syntax.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test()
+ public void testPLAINSameUnprivAuthzIDSuccessfulUColon()
+ throws Exception
+ {
+ String[] args =
+ {
+ "-h", "127.0.0.1",
+ "-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
+ "-o", "mech=PLAIN",
+ "-o", "authid=u:unprivileged.user",
+ "-o", "authzid=u:unprivileged.user",
+ "-w", "password",
+ "-b", "o=test",
+ "-s", "base",
+ "(objectClass=*)"
+ };
+
+ assertEquals(LDAPSearch.mainSearch(args, false, null, System.err), 0);
+ }
+
+
+
+ /**
+ * Tests to ensure that the server will properly respect the PROXIED_AUTH
+ * privilege when attempting to perform PLAIN authentication when an
+ * alternate authorization ID is specified with an authentication identity
+ * that does not have sufficient privileges and using the "u:" syntax.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test()
+ public void testPLAINDifferentAuthzIDFailedUColon()
+ throws Exception
+ {
+ String[] args =
+ {
+ "-h", "127.0.0.1",
+ "-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
+ "-o", "mech=PLAIN",
+ "-o", "authid=u:unprivileged.user",
+ "-o", "authzid=u:privileged.user",
+ "-w", "password",
+ "-b", "o=test",
+ "-s", "base",
+ "(objectClass=*)"
+ };
+
+ assertFalse(LDAPSearch.mainSearch(args, false, null, null) == 0);
+ }
+
+
+
+ /**
* Tests the ability to update the set of privileges for a user on the fly
* and have them take effect immediately.
*
--
Gitblit v1.10.0