AciContainer.java revision 88f16d892d54fd8c3e190cc1f6363638b11ae1a3
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at legal-notices/CDDLv1_0.txt.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information:
* Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*
*
* Copyright 2008 Sun Microsystems, Inc.
* Portions Copyright 2011-2015 ForgeRock AS
*/
/**
* The AciContainer class contains all of the needed information to perform
* both target match and evaluate an ACI. Target matching is the process
* of testing if an ACI is applicable to an operation, and evaluation is
* the actual access evaluation of the ACI.
*/
public abstract class AciContainer
implements AciTargetMatchContext, AciEvalContext {
/**
* The allow and deny lists.
*/
/**
* The attribute type in the resource entry currently being evaluated.
*/
private AttributeType attributeType;
/**
* The attribute type value in the resource entry currently being
* evaluated.
*/
private ByteString attributeValue;
/**
* True if this is the first attribute type in the resource entry being
* evaluated.
*/
private boolean isFirst;
/**
* True if an entry test rule was seen during target matching of an ACI
* entry. A entry test rule is an ACI with targetattrs target keyword.
*/
private boolean isEntryTestRule;
/**
* The right mask to use in the evaluation of the LDAP operation.
*/
private int rightsMask;
/**
* The entry being evaluated (resource entry).
*/
private Entry resourceEntry;
/**
* The client connection information.
*/
private final ClientConnection clientConnection;
/**
* The operation being evaluated.
*/
/**
* True if a targattrfilters match was found.
*/
private boolean targAttrFiltersMatch;
/**
* The authorization entry currently being evaluated. If proxied
* authorization is being used and the handler is doing a proxy access
* check, then this entry will switched to the original authorization entry
* rather than the proxy ID entry. If the check succeeds, it will be
* switched back for non-proxy access checking. If proxied authentication
* is not being used then this entry never changes.
*/
private Entry authorizationEntry;
/**
* Used to save the current authorization entry when the authorization
* entry is switched during a proxy access check.
*/
private final Entry saveAuthorizationEntry;
/**
* This entry is only used if proxied authorization is being used. It is
* the original authorization entry before the proxied authorization change.
*/
private Entry origAuthorizationEntry;
/**
* True if proxied authorization is being used.
*/
private boolean proxiedAuthorization;
/**
* Used by proxied authorization processing. True if the entry has already
* been processed by an access proxy check. Some operations might perform
* several access checks on the same entry (modify DN), this
* flag is used to bypass the proxy check after the initial evaluation.
*/
private boolean seenEntry;
/**
* True if geteffectiverights evaluation is in progress.
*/
private boolean isGetEffectiveRightsEval;
/**
* True if the operation has a geteffectiverights control.
*/
private boolean hasGetEffectiveRightsControl;
/**
* The geteffectiverights authzID in DN format.
*/
/**
* True if the authZid should be used as the client DN, only used in
* geteffectiverights evaluation.
*/
private boolean useAuthzid;
/**
* The list of specific attributes to get rights for, in addition to
* any attributes requested in the search.
*/
/**
* Table of ACIs that have targattrfilter keywords that matched. Used
* in geteffectiverights attributeLevel write evaluation.
*/
/**
* The name of a ACI that decided an evaluation and contained a
* targattrfilter keyword. Used in geteffectiverights attributeLevel
* write evaluation.
*/
private String targAttrFiltersAciName;
/**
* containing a targattrfilter keyword. Used in geteffectiverights
* attributeLevel write evaluation.
*/
private int targAttrMatch;
/**
* The ACI that decided the last evaluation. Used in geteffectiverights
* loginfo processing.
*/
private Aci decidingAci;
/**
* The reason the last evaluation decision was made. Used both
* in geteffectiverights loginfo processing and attributeLevel write
* evaluation.
*/
private EnumEvalReason evalReason;
/**
* A summary string holding the last evaluation information in textual
* format. Used in geteffectiverights loginfo processing.
*/
private String summaryString;
/**
* Flag used to determine if ACI all attributes target matched.
*/
private int evalAllAttributes;
/**
* String used to hold a control OID string.
*/
private String controlOID;
/**
* String used to hold an extended operation OID string.
*/
/**
* AuthenticationInfo class to use.
*/
private AuthenticationInfo authInfo;
/**
* This constructor is used by all currently supported LDAP operations
* except the generic access control check that can be used by
* plugins.
*
* @param operation The Operation object being evaluated and target
* matching.
*
* @param rights The rights array to use in evaluation and target matching.
*
* @param entry The current entry being evaluated and target matched.
*/
this.resourceEntry=entry;
//If the proxied authorization control was processed, then the operation
//will contain an attachment containing the original authorization entry.
this.origAuthorizationEntry =
//The ACI_READ right at constructor time can only be the result of the
//AciHandler.filterEntry method. This method processes the
//geteffectiverights control, so it needs to check for it. There are
//two other checks done, because the resource entry passed to that method
//is filtered (it may not contain enough attribute information
//to evaluate correctly). See the the comments below.
//Checks if a geteffectiverights control was sent and
//sets up the structures needed.
if (getEffectiveRightsControl != null
&& operation instanceof SearchOperation)
{
hasGetEffectiveRightsControl = true;
this.authzid = getClientDN();
}
//If an ACI evaluated because of an Targetattr="*", then the
//AciHandler.maySend method signaled this via adding this attachment
//string.
if(allUserAttrs != null)
//If an ACI evaluated because of an Targetattr="+", then the
//AciHandler.maySend method signaled this via adding this attachment
//string.
if(allOpAttrs != null)
}
//Reference the current authorization entry, so it can be put back
//if an access proxy check was performed.
this.saveAuthorizationEntry=this.authorizationEntry;
this.rightsMask = rights;
}
/**
* This constructor is used by the generic access control check.
*
* @param operation The operation to use in the access evaluation.
* @param e The entry to check access for.
* @param authInfo The authentication information to use in the evaluation.
* @param rights The rights to check access of.
*/
int rights) {
this.resourceEntry=e;
this.saveAuthorizationEntry=this.authorizationEntry;
this.rightsMask = rights;
}
/**
* Returns true if an entry has already been processed by an access proxy
* check.
*
* @return True if an entry has already been processed by an access proxy
* check.
*/
public boolean hasSeenEntry() {
return this.seenEntry;
}
/**
* Set to true if an entry has already been processed by an access proxy
* check.
*
* @param val The value to set the seenEntry boolean to.
*/
public void setSeenEntry(boolean val) {
}
/**
* {@inheritDoc}
*/
public boolean isProxiedAuthorization() {
return this.proxiedAuthorization;
}
/**
* {@inheritDoc}
*/
public boolean isGetEffectiveRightsEval() {
return this.isGetEffectiveRightsEval;
}
/**
* The container is going to be used in a geteffectiverights evaluation, set
* the flag isGetEffectiveRightsEval to true.
*/
public void setGetEffectiveRightsEval() {
this.isGetEffectiveRightsEval=true;
}
/**
* Return true if the container is being used in a geteffectiverights
* evaluation.
*
* @return True if the container is being used in a geteffectiverights
* evaluation.
*/
public boolean hasGetEffectiveRightsControl() {
return this.hasGetEffectiveRightsControl;
}
/**
* Use the DN from the geteffectiverights control's authzId as the
* client DN, rather than the authorization entry's DN.
*
* @param v The valued to set the useAuthzid to.
*/
public void useAuthzid(boolean v) {
this.useAuthzid=v;
}
/**
* Return the list of additional attributes specified in the
* geteffectiverights control.
*
* @return The list of attributes to return rights information about in the
* entry.
*/
return this.specificAttrs;
}
/**
* {@inheritDoc}
*/
}
/**
* {@inheritDoc}
*/
}
/**
* {@inheritDoc}
*/
public boolean isTargAttrFilterMatchAciEmpty() {
return this.targAttrFilterAcis.isEmpty();
}
/**
* Reset the values used by the geteffectiverights evaluation to
* original values. The geteffectiverights evaluation uses the same container
* repeatedly for different rights evaluations (read, write, proxy,...) and
* this method resets variables that are specific to a single evaluation.
*/
public void resetEffectiveRightsParams() {
this.targAttrFilterAcis.clear();
this.decidingAci=null;
this.evalReason=null;
this.targAttrFiltersMatch=false;
this.summaryString=null;
this.targAttrMatch=0;
}
/**
* {@inheritDoc}
*/
this.targAttrFiltersAciName=name;
}
/**
* {@inheritDoc}
*/
public String getTargAttrFiltersAciName() {
return this.targAttrFiltersAciName;
}
/**
* {@inheritDoc}
*/
public void setTargAttrFiltersMatchOp(int flag) {
this.targAttrMatch |= flag;
}
/**
* {@inheritDoc}
*/
public boolean hasTargAttrFiltersMatchOp(int flag) {
}
/**
* {@inheritDoc}
*/
public String getDecidingAciName() {
if(this.decidingAci != null)
return this.decidingAci.getName();
else return null;
}
/** {@inheritDoc} */
{
this.evalReason = reason;
this.decidingAci = decidingAci;
}
/**
* {@inheritDoc}
*/
public EnumEvalReason getEvalReason() {
return this.evalReason;
}
/**
* {@inheritDoc}
*/
this.summaryString=summary;
}
/**
* {@inheritDoc}
*/
public String getEvalSummary() {
return this.summaryString;
}
/**
* Returns true if the geteffectiverights control's authZid DN is equal to the
* authorization entry's DN.
*
* @return True if the authZid is equal to the authorization entry's DN.
*/
public boolean isAuthzidAuthorizationDN() {
}
/**
* If the specified value is true, then the original authorization entry,
* which is the entry before the switch performed by the proxied
* authorization control processing should be set to the current
* authorization entry. If the specified value is false then the proxied
* authorization entry is switched back using the saved copy.
* @param val The value used to select the authorization entry to use.
*/
public void useOrigAuthorizationEntry(boolean val) {
if(val)
else
}
/**
* {@inheritDoc}
*/
}
/**
* {@inheritDoc}
*/
}
/**
* {@inheritDoc}
*/
public AttributeType getCurrentAttributeType() {
return attributeType;
}
/**
* {@inheritDoc}
*/
public ByteString getCurrentAttributeValue() {
return attributeValue;
}
/**
* {@inheritDoc}
*/
}
/**
* {@inheritDoc}
*/
}
/**
* {@inheritDoc}
*/
public boolean isFirstAttribute() {
return isFirst;
}
/**
* {@inheritDoc}
*/
public void setIsFirstAttribute(boolean val) {
}
/**
* {@inheritDoc}
*/
public boolean hasEntryTestRule() {
return isEntryTestRule;
}
/**
* {@inheritDoc}
*/
public void setEntryTestRule(boolean val) {
}
/**
* {@inheritDoc}
*/
public Entry getResourceEntry() {
return resourceEntry;
}
/**
* {@inheritDoc}
*/
public Entry getClientEntry() {
return this.authorizationEntry;
}
/**
* {@inheritDoc}
*/
return denyList;
}
/**
* {@inheritDoc}
*/
return allowList;
}
/**
* {@inheritDoc}
*/
public boolean isDenyEval() {
}
/**
* {@inheritDoc}
*/
public boolean isAnonymousUser() {
return !authInfo.isAuthenticated();
}
/**
* {@inheritDoc}
*/
public DN getClientDN() {
if(this.useAuthzid)
return this.authzid;
else if (this.authorizationEntry != null)
return this.authorizationEntry.getName();
}
/**
* {@inheritDoc}
*/
public DN getResourceDN() {
return resourceEntry.getName();
}
/**
* {@inheritDoc}
* <p>
* JNR: I find the implementation in this method dubious.
*
* @see EnumRight#hasRights(int, int)
*/
}
/**
* {@inheritDoc}
*/
public int getRights() {
return this.rightsMask;
}
/**
* {@inheritDoc}
*/
this.rightsMask=rights;
}
/**
* {@inheritDoc}
*/
public String getHostName() {
}
/**
* {@inheritDoc}
*/
public InetAddress getRemoteAddress() {
return clientConnection.getRemoteAddress();
}
/**
* {@inheritDoc}
*/
public boolean isAddOperation() {
return operation instanceof AddOperation;
}
/**
* {@inheritDoc}
*/
public void setTargAttrFiltersMatch(boolean v) {
this.targAttrFiltersMatch=v;
}
/**
* {@inheritDoc}
*/
public boolean getTargAttrFiltersMatch() {
return targAttrFiltersMatch;
}
/**
* {@inheritDoc}
*/
public String getControlOID() {
return controlOID;
}
/**
* {@inheritDoc}
*/
public String getExtOpOID() {
return extOpOID;
}
/**
* Set the the controlOID value to the specified oid string.
*
* @param oid The control oid string.
*/
this.controlOID=oid;
}
/**
* Set the extended operation OID value to the specified oid string.
*
* @param oid The extended operation oid string.
*/
}
/**
* {@inheritDoc}
*/
/**
* None actually means any, in that we don't care what method was used.
* This doesn't seem very intuitive or useful, but that's the way it is.
*/
} else {
/*
* Some kind of authentication is required.
*/
if(authInfo.isAuthenticated()) {
}
/*
* This means authentication using a certificate over TLS.
*
* We check the following:
* - SASL EXTERNAL has been used, and
* - TLS is the security provider, and
* - The client provided a certificate.
*/
if(clientConnection instanceof LDAPClientConnection) {
}
}
} else {
// A particular SASL mechanism.
}
}
}
}
return matched;
}
/**
* {@inheritDoc}
*/
try {
if(useAuthzid) {
}
Entry e = getClientEntry();
if (e != null) {
}
} catch (DirectoryException ex) {
return false;
}
}
/**
* {@inheritDoc}
* <p>
* JNR: I find the implementation in this method dubious.
*
* @see EnumRight#getEnumRight(int)
*/
public String rightToString() {
if(hasRights(ACI_SEARCH))
return "search";
else if(hasRights(ACI_COMPARE))
return "compare";
return "read";
else if(hasRights(ACI_DELETE))
return "delete";
return "add";
return "write";
return "proxy";
else if(hasRights(ACI_IMPORT))
return "import";
else if(hasRights(ACI_EXPORT))
return "export";
return "selfwrite";
return null;
}
/**
* {@inheritDoc}
*/
public void setEvalUserAttributes(int v) {
if(v == ACI_FOUND_USER_ATTR_RULE) {
} else
}
}
/**
* {@inheritDoc}
*/
public void setEvalOpAttributes(int v) {
if(v == ACI_FOUND_OP_ATTR_RULE) {
} else
}
}
/**
* {@inheritDoc}
*/
public boolean hasEvalUserAttributes() {
return hasAttribute(ACI_FOUND_USER_ATTR_RULE);
}
/**
* {@inheritDoc}
*/
public boolean hasEvalOpAttributes() {
return hasAttribute(ACI_FOUND_OP_ATTR_RULE);
}
/**
* Return true if the evaluating ACI contained a targetattr all
* user attributes rule match.
*
* @return True if the above condition was seen.
*/
public boolean hasAllUserAttributes() {
return hasAttribute(ACI_USER_ATTR_STAR_MATCHED);
}
/**
* Return true if the evaluating ACI contained a targetattr all
* operational attributes rule match.
*
* @return True if the above condition was seen.
*/
public boolean hasAllOpAttributes() {
return hasAttribute(ACI_OP_ATTR_PLUS_MATCHED);
}
private boolean hasAttribute(int aciAttribute)
{
}
/**
* {@inheritDoc}
*/
public void clearEvalAttributes(int v) {
if(v == 0)
else
evalAllAttributes &= ~v;
}
/**
* {@inheritDoc}
*/
public int getCurrentSSF() {
return clientConnection.getSSF();
}
/** {@inheritDoc} */
{
if (attributeType != null)
{
if (attributeValue != null)
{
}
}
if (evalReason != null)
{
if (decidingAci != null)
{
}
}
}
{
{
}
}
{
{
}
return 0;
}
}