AciContainer.java revision 31ef6298b4179ddca52d4b1d0aad873af9d17155
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at
* trunk/opends/resource/legal-notices/OpenDS.LICENSE
* or https://OpenDS.dev.java.net/OpenDS.LICENSE.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at
* trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
* add the following below this CDDL HEADER, with the fields enclosed
* by brackets "[]" replaced with your own identifying information:
* Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*
*
* Portions Copyright 2007 Sun Microsystems, Inc.
*/
package org.opends.server.authorization.dseecompat;
import org.opends.server.types.*;
import org.opends.server.api.ClientConnection;
import org.opends.server.api.Group;
import org.opends.server.core.AddOperation;
import org.opends.server.core.Operation;
import org.opends.server.extensions.TLSConnectionSecurityProvider;
import org.opends.server.util.ServerConstants;
import java.net.InetAddress;
import java.util.LinkedList;
/**
* 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.
*/
private LinkedList<Aci> denyList, allowList;
/*
* 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 AttributeValue attributeValue;
/*
* True if this is the first attribute type in the resource entry being
* evaluated.
*/
private boolean isFirst = false;
/*
* 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 = false;
/*
* True if the evaluation of an ACI is from the deny list.
*/
private boolean isDenyEval;
/*
* True if the evaluation is a result of an LDAP add operation.
*/
private boolean isAddOp=false;
/*
* The rights to use in the evaluation of the LDAP operation.
*/
private int rights;
/*
* The entry being evaluated (resource entry).
*/
private Entry resourceEntry;
/*
* The client connection information.
*/
private ClientConnection clientConnection;
/*
* The operation being evaluated.
*/
private Operation operation;
/*
* True if a targattrfilters match was found.
*/
private boolean targAttrFiltersMatch=false;
/**
* This constructor is used by all currently supported LDAP operations.
*
* @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.
*/
protected AciContainer(Operation operation, int rights, Entry entry) {
this.resourceEntry=entry;
this.operation=operation;
this.clientConnection=operation.getClientConnection();
if(operation instanceof AddOperation)
this.isAddOp=true;
this.rights = rights;
}
/**
* The list of deny ACIs. These are all of the applicable
* ACIs that have a deny permission. Note that an ACI can
* be on both allow and deny list if it has multiple
* permission-bind rule pairs.
*
* @param denys The list of deny ACIs.
*/
public void setDenyList(LinkedList<Aci> denys) {
denyList=denys;
}
/**
* The list of allow ACIs. These are all of the applicable
* ACIs that have an allow permission.
*
* @param allows The list of allow ACIs.
*/
public void setAllowList(LinkedList<Aci> allows) {
allowList=allows;
}
/**
* Return the current attribute type being evaluated.
* @return Attribute type being evaluated.
*/
public AttributeType getCurrentAttributeType() {
return attributeType;
}
/**
* Return the current attribute type value being evaluated.
* @return Attribute type value being evaluated.
*/
public AttributeValue getCurrentAttributeValue() {
return attributeValue;
}
/**
* Set the attribute type to be evaluated.
* @param type The attribute type to evaluate.
*/
public void setCurrentAttributeType(AttributeType type) {
attributeType=type;
}
/**
* Set the attribute type value to be evaluated.
* @param value The attribute type value to evaluate.
*/
public void setCurrentAttributeValue(AttributeValue value) {
attributeValue=value;
}
/**
* Check is this the first attribute being evaluated in an entry.
* @return True if it is the first attribute.
*/
public boolean isFirstAttribute() {
return isFirst;
}
/**
* Set if this is the first attribute in the entry.
* @param val True if this is the first attribute being evaluated in the
* entry.
*/
public void setIsFirstAttribute(boolean val) {
isFirst=val;
}
/**
* Check if an entry test rule was seen during target evaluation.
* @return True if an entry test rule was seen.
*/
public boolean hasEntryTestRule() {
return isEntryTestRule;
}
/**
* Used to set if an entry test rule was seen during target evaluation.
* @param val Set to true if an entry test rule was seen.
*/
public void setEntryTestRule(boolean val) {
isEntryTestRule=val;
}
/**
* Get the entry being evaluated (known as the resource entry).
* @return The entry being evaluated.
*/
public Entry getResourceEntry() {
return resourceEntry;
}
/**
* Get the entry that corresponds to the client DN.
* @return The client entry.
*/
public Entry getClientEntry() {
return operation.getAuthorizationEntry();
}
/**
* Get the deny list of ACIs.
* @return The deny ACI list.
*/
public LinkedList<Aci> getDenyList() {
return denyList;
}
/**
* Get the allow list of ACIs.
* @return The allow ACI list.
*/
public LinkedList<Aci> getAllowList() {
return allowList;
}
/**
* Check is this is a deny ACI evaluation.
* @return True if the evaluation is using an ACI from
* deny list.
*/
public boolean isDenyEval() {
return isDenyEval;
}
/**
* Check is this operation bound anonymously.
* @return True if the authentication is anonymous.
*/
public boolean isAnonymousUser() {
return !clientConnection.getAuthenticationInfo().isAuthenticated();
}
/**
* Set the deny evaluation flag.
* @param val True if this evaluation is a deny ACI.
*/
public void setDenyEval(boolean val) {
isDenyEval = val;
}
/**
* Returns the client authorization DN known as the client DN.
* @return The client's authorization DN.
*/
public DN getClientDN() {
return operation.getAuthorizationDN();
}
/**
* Get the DN of the entry being evaluated.
* @return The DN of the entry.
*/
public DN getResourceDN() {
return resourceEntry.getDN();
}
/**
* Checks if the container's rights has the specified rights.
* @param rights The rights to check for.
* @return True if the container's rights has the specified rights.
*/
public boolean hasRights(int rights) {
return (this.rights & rights) != 0;
}
/**
* Return the rights set for this container's LDAP operation.
* @return The rights set for the container's LDAP operation.
*/
public int getRights() {
return this.rights;
}
/**
* Sets the rights for this container to the specified rights.
* @param rights The rights to set the container's rights to.
*/
public void setRights(int rights) {
this.rights=rights;
}
/**
* Gets the hostname of the remote client.
* @return Cannonical hostname of remote client.
*/
public String getHostName() {
return clientConnection.getRemoteAddress().getCanonicalHostName();
}
/**
* Gets the remote client's address information.
* @return Remote client's address.
*/
public InetAddress getRemoteAddress() {
return clientConnection.getRemoteAddress();
}
/**
* Return true if the current operation is a LDAP add operation.
* @return True if this is an add operation.
*/
public boolean isAddOperation() {
return isAddOp;
}
/**
* Set to true if the ACI had a targattrfilter rule that matched.
* @param v The value to use.
*/
public void setTargAttrFiltersMatch(boolean v) {
this.targAttrFiltersMatch=v;
}
/**
* Return the value of the targAttrFiltersMatch variable. This is set to
* true if the ACI had a targattrfilter rule that matched.
* @return True if the ACI had a targattrfilter rule that matched.
*/
public boolean getTargAttrFiltersMatch() {
return targAttrFiltersMatch;
}
/**
* Try to determine the authentication information from the current
* client connection. The checks are for simple and SASL, anything else
* is not a match. If the bind rule requires any SSL client authentication
* information then the "wantSSL" flag should be set. This code is used by
* the authmethod bind rule keyword.
*
* @param wantSSL True if the bind rule needs the ssl client auth check.
* @return Return an enumeration containing the authentication method
* type for this client connection.
*/
public EnumAuthMethod getAuthenticationMethod(boolean wantSSL) {
EnumAuthMethod method=EnumAuthMethod.AUTHMETHOD_NOMATCH;
AuthenticationInfo authInfo=clientConnection.getAuthenticationInfo();
if(authInfo.isAuthenticated()) {
if(authInfo.hasAuthenticationType(AuthenticationType.SIMPLE))
method=EnumAuthMethod.AUTHMETHOD_SIMPLE;
else if(authInfo.hasAuthenticationType(AuthenticationType.SASL))
method=getSaslAuthenticationMethod(authInfo, wantSSL);
else
method=EnumAuthMethod.AUTHMETHOD_NOMATCH;
}
return method;
}
/*
* TODO This method needs to be tested.
* TODO Investigate multi-factor authentication.
* Second, OpenDS is devised so that it could be possible to use
* multi-factor or step-up authentication, in which the same client
* has provided multiple forms of credentials, but this method
* expects only a single authentication type.
*/
/**
* This method attempts to figure out what the SASL method was/is or
* what the client auth is.
* @param authInfo The authentication information to use.
* @param wantSSL The bin drule wants the SSL client auth status.
* @return An enumeration containing the SASL bind information.
*/
private EnumAuthMethod
getSaslAuthenticationMethod(AuthenticationInfo authInfo, boolean wantSSL) {
EnumAuthMethod method=EnumAuthMethod.AUTHMETHOD_NOMATCH;
if(authInfo.hasAuthenticationType(AuthenticationType.SASL)) {
if(authInfo.hasSASLMechanism(ServerConstants.
SASL_MECHANISM_DIGEST_MD5))
method=EnumAuthMethod.AUTHMETHOD_SASL_MD5;
else if(authInfo.hasSASLMechanism(ServerConstants.
SASL_MECHANISM_GSSAPI))
method=EnumAuthMethod.AUTHMETHOD_SASL_GSSAPI;
else if(authInfo.hasSASLMechanism(ServerConstants.
SASL_MECHANISM_EXTERNAL)) {
/*
* The bind rule wants ssl client auth information. Need the
* security provider to see if the clientAuthPolicy is
* required. If it is optional, we really can't determine if
* the client auth.
*/
if(wantSSL) {
String mechName=
clientConnection.getConnectionSecurityProvider().
getSecurityMechanismName();
if(mechName.equalsIgnoreCase("TLS")) {
TLSConnectionSecurityProvider tlsProv=
(TLSConnectionSecurityProvider)clientConnection.
getConnectionSecurityProvider();
SSLClientAuthPolicy clientAuthPolicy=
tlsProv.getSSLClientAuthPolicy();
if(clientAuthPolicy == SSLClientAuthPolicy.REQUIRED)
method=EnumAuthMethod.AUTHMETHOD_SSL;
} else
method=EnumAuthMethod.AUTHMETHOD_NOMATCH;
} else {
method=EnumAuthMethod.AUTHMETHOD_SASL_EXTERNAL;
}
} else
method=EnumAuthMethod.AUTHMETHOD_NOMATCH;
}
return method;
}
/**
* Convienance method that checks if the the clientDN is a member of the
* specified group.
* @param group The group to check membership in.
* @return True if the clientDN is a member of the specified group.
*/
public boolean isMemberOf(Group group) {
boolean ret;
try {
ret=clientConnection.isMemberOf(group, operation);
} catch (DirectoryException ex) {
ret=false;
}
return ret;
}
}