| opends/resource/config/config.ldif | ●●●●● patch | view | raw | blame | history | |
| opends/resource/schema/00-core.ldif | ●●●●● patch | view | raw | blame | history | |
| opends/src/server/org/opends/server/authorization/dseecompat/AciHandler.java | ●●●●● patch | view | raw | blame | history | |
| opends/src/server/org/opends/server/authorization/dseecompat/AciMessages.java | ●●●●● patch | view | raw | blame | history | |
| opends/src/server/org/opends/server/messages/CoreMessages.java | ●●●●● patch | view | raw | blame | history | |
| opends/src/server/org/opends/server/messages/MessageHandler.java | ●●●●● patch | view | raw | blame | history | |
| opends/src/server/org/opends/server/schema/AciSyntax.java | ●●●●● patch | view | raw | blame | history | |
| opends/src/server/org/opends/server/schema/SchemaConstants.java | ●●●●● patch | view | raw | blame | history | |
| opends/tests/unit-tests-testng/src/server/org/opends/server/TestAccessLogger.java | ●●●●● patch | view | raw | blame | history |
opends/resource/config/config.ldif
@@ -1260,6 +1260,13 @@ ds-cfg-syntax-class: org.opends.server.schema.AbsoluteSubtreeSpecificationSyntax ds-cfg-syntax-enabled: true dn: cn=Sun-defined Access Control Information,cn=Syntaxes,cn=config objectClass: top objectClass: ds-cfg-attribute-syntax cn: Sun-defined Access Control Information ds-cfg-syntax-class: org.opends.server.schema.AciSyntax ds-cfg-syntax-enabled: true dn: cn=Attribute Type Description,cn=Syntaxes,cn=config objectClass: top objectClass: ds-cfg-attribute-syntax opends/resource/schema/00-core.ldif
@@ -357,7 +357,7 @@ USAGE dSAOperation X-ORIGIN 'draft-ietf-ldup-subentry' ) attributeTypes: ( 2.16.840.1.113730.3.1.55 NAME 'aci' DESC 'Sun-defined access control information attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 USAGE directoryOperation SYNTAX 1.3.6.1.4.1.26027.1.3.4 USAGE directoryOperation X-ORIGIN 'Sun Java System Directory Server' ) attributeTypes: ( 2.16.840.1.113730.3.1.542 NAME 'nsUniqueId' DESC 'Sun-defined unique identifier' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 @@ -517,7 +517,7 @@ DESC 'named subordinate reference object' STRUCTURAL MUST ref X-ORIGIN 'RFC 3296' ) objectClasses: ( 2.16.840.1.113719.2.142.6.1.1 NAME 'ldapSubEntry' DESC 'LDAP Subentry class, version 1' SUP top STRUCTURAL MAY ( cn ) DESC 'LDAP Subentry class, version 1' SUP top STRUCTURAL MAY ( cn ) X-ORIGIN 'draft-ietf-ldup-subentry' ) objectClasses: ( 1.3.6.1.4.1.7628.5.6.1.1 NAME 'inheritableLDAPSubEntry' DESC 'Inheritable LDAP Subentry class, version 1' SUP ldapSubEntry opends/src/server/org/opends/server/authorization/dseecompat/AciHandler.java
@@ -57,7 +57,7 @@ public static AttributeType aciType; /** * Constructor that registers the message catalog, creates the ACI list * Constructor that creates the ACI list * class that manages the ACI list. Instantiates and registers the change * notification listener that is used to manage the ACI list on * modifications and the backend initialization listener that is used to @@ -65,7 +65,6 @@ * are initialized/finalized. */ public AciHandler() { AciMessages.registerMessages(); aciList = new AciList(); AciListenerManager aciListenerMgr = new AciListenerManager(aciList); @@ -88,11 +87,30 @@ ModifyOperation operation, boolean skipAccessCheck) { Entry resourceEntry=container.getResourceEntry(); DN dn=resourceEntry.getDN(); List<Modification> modifications=container.getModifications(); for(Modification m : modifications) { Attribute modAttr=m.getAttribute(); AttributeType modType=modAttr.getAttributeType(); if(modType.equals(aciType)) { /* * Check that the operation has modify privileges if * it contains an "aci" attribute type. */ if (!operation.getClientConnection(). hasPrivilege(Privilege.MODIFY_ACL, operation)) { int msgID = MSGID_ACI_MODIFY_FAILED_PRIVILEGE; String message = getMessage(msgID, String.valueOf(container.getResourceDN()), String.valueOf(container.getClientDN())); logError(ErrorLogCategory.ACCESS_CONTROL, ErrorLogSeverity.SEVERE_WARNING, message, msgID); return false; } } switch(m.getModificationType()) { case DELETE: case REPLACE: @@ -157,46 +175,6 @@ } break; } /* Check if the modification type has an "aci" attribute type. If so, check the syntax of that attribute value. Fail the the operation if the syntax check fails. */ if(modType.equals(aciType)) { try { /* * Check that the operation has modify privileges if * it contains an "aci" attribute type. Flip the * boolean to false so this check isn't made again * if there are several ACI values being added. */ if(checkPrivileges) { if (!operation.getClientConnection(). hasPrivilege(Privilege.MODIFY_ACL, operation)) { int msgID = MSGID_ACI_MODIFY_FAILED_PRIVILEGE; String message = getMessage(msgID, String.valueOf(container.getResourceDN()), String.valueOf(container.getClientDN())); logError(ErrorLogCategory.ACCESS_CONTROL, ErrorLogSeverity.SEVERE_WARNING, message, msgID); return false; } checkPrivileges=false; } Aci.decode(v.getValue(),dn); } catch (AciException ex) { int msgID = MSGID_ACI_MODIFY_FAILED_DECODE; String message = getMessage(msgID, String.valueOf(dn), ex.getMessage()); logError(ErrorLogCategory.ACCESS_CONTROL, ErrorLogSeverity.SEVERE_WARNING, message, msgID); return false; } } } } } @@ -454,63 +432,6 @@ } /** * Evaluate an entry to be added to see if it has any "aci" * attribute type. If it does, examines each "aci" attribute type * value for syntax errors. All of the "aci" attribute type values * must pass syntax check for the add operation to proceed. Any * entry with an "aci" attribute type must have "modify-acl" * privileges. * * @param entry The entry to be examined. * @param operation The operation to to check privileges on. * @param clientDN The authorization DN. * @return True if the entry has no ACI attributes or if all of the "aci" * attributes values pass ACI syntax checking. */ private boolean verifySyntax(Entry entry, Operation operation, DN clientDN) { if(entry.hasOperationalAttribute(aciType)) { /* * Check that the operation has "modify-acl" privileges since the * entry to be added has an "aci" attribute type. */ if (!operation.getClientConnection(). hasPrivilege(Privilege.MODIFY_ACL, operation)) { int msgID = MSGID_ACI_ADD_FAILED_PRIVILEGE; String message = getMessage(msgID, String.valueOf(entry.getDN()), String.valueOf(clientDN)); logError(ErrorLogCategory.ACCESS_CONTROL, ErrorLogSeverity.SEVERE_WARNING, message, msgID); return false; } List<Attribute> attributeList = entry.getOperationalAttribute(aciType, null); for (Attribute attribute : attributeList) { for (AttributeValue value : attribute.getValues()) { try { DN dn=entry.getDN(); Aci.decode(value.getValue(),dn); } catch (AciException ex) { int msgID = MSGID_ACI_ADD_FAILED_DECODE; String message = getMessage(msgID, String.valueOf(entry.getDN()), ex.getMessage()); logError(ErrorLogCategory.ACCESS_CONTROL, ErrorLogSeverity.SEVERE_WARNING, message, msgID); return false; } } } } return true; } /** * Check access using the accessAllowed method. The * LDAP add, compare, modify and delete operations use this function. * The other supported LDAP operations have more specialized checks. @@ -534,11 +455,28 @@ AciLDAPOperationContainer operationContainer = new AciLDAPOperationContainer(operation, ACI_ADD); boolean ret=isAllowed(operationContainer,operation); //LDAP add needs a verify ACI syntax step in case any //"aci" attribute types are being added. if(ret) ret=verifySyntax(operation.getEntryToAdd(), operation, operationContainer.getClientDN()); if(ret) { Entry entry = operation.getEntryToAdd(); if(entry.hasOperationalAttribute(aciType)) { /* * Check that the operation has "modify-acl" privileges since the * entry to be added has an "aci" attribute type. */ if (!operation.getClientConnection(). hasPrivilege(Privilege.MODIFY_ACL, operation)) { int msgID = MSGID_ACI_ADD_FAILED_PRIVILEGE; String message = getMessage(msgID, String.valueOf(entry.getDN()), String.valueOf(operationContainer.getClientDN())); logError(ErrorLogCategory.ACCESS_CONTROL, ErrorLogSeverity.SEVERE_WARNING, message, msgID); ret = false; } } } return ret; } opends/src/server/org/opends/server/authorization/dseecompat/AciMessages.java
@@ -474,24 +474,6 @@ CATEGORY_MASK_ACCESS_CONTROL | 45; /** * The message ID for the ACI message that will be generated when a client * attempts to add an entry with the "aci" attribute type * and the ACI decode failed because of an syntax error. This takes one * argument, which is the message string thrown by the AciException. */ public static final int MSGID_ACI_ADD_FAILED_DECODE = CATEGORY_MASK_ACCESS_CONTROL | SEVERITY_MASK_SEVERE_WARNING | 46; /** * The message ID for the ACI message that will be generated when a client * attempts to perform a modification on an "aci" attribute type * and the ACI decode failed because of a syntax error. This takes one * argument, which is the message string thrown by the AciException. */ public static final int MSGID_ACI_MODIFY_FAILED_DECODE = CATEGORY_MASK_ACCESS_CONTROL | SEVERITY_MASK_SEVERE_WARNING | 47; /** * The message ID for the ACI message that will be generated when * an ACI decode failed because of an syntax error. This message is usually * generated by an invalid ACI that was added during import which @@ -876,16 +858,6 @@ "attribute type in the entry \"%s\" failed, because the" + "authorization DN \"%s\" lacked modify-acl privileges."); registerMessage(MSGID_ACI_ADD_FAILED_DECODE, "An attempt to add the entry \"%s\" containing" + " an aci attribute type failed because of the following" + " reason: %s"); registerMessage(MSGID_ACI_MODIFY_FAILED_DECODE, "An attempt to modify an aci "+ "attribute type in the entry \"%s\" failed "+ "because of the following reason: %s"); registerMessage(MSGID_ACI_ADD_LIST_FAILED_DECODE, "An attempt to decode an Access Control Instruction (ACI)" + " failed because of the following reason: %s"); opends/src/server/org/opends/server/messages/CoreMessages.java
@@ -6666,7 +6666,7 @@ registerMessage(MSGID_ADD_OP_INVALID_SYNTAX, "Entry \"%s\" contains an value \"%s\" for attribute %s " + "Entry \"%s\" contains a value \"%s\" for attribute %s " + "that is invalid according to the syntax for that " + "attribute: %s."); registerMessage(MSGID_ADD_ATTR_IS_OBSOLETE, opends/src/server/org/opends/server/messages/MessageHandler.java
@@ -28,6 +28,8 @@ import org.opends.server.authorization.dseecompat.AciMessages; import java.util.concurrent.ConcurrentHashMap; import java.util.IllegalFormatException; @@ -281,6 +283,7 @@ BackendMessages.registerMessages(); ToolMessages.registerMessages(); TaskMessages.registerMessages(); AciMessages.registerMessages(); } opends/src/server/org/opends/server/schema/AciSyntax.java
New file @@ -0,0 +1,262 @@ /* * 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 2006-2007 Sun Microsystems, Inc. */ package org.opends.server.schema; import org.opends.server.api.ApproximateMatchingRule; import org.opends.server.api.AttributeSyntax; import org.opends.server.api.EqualityMatchingRule; import org.opends.server.api.OrderingMatchingRule; import org.opends.server.api.SubstringMatchingRule; import org.opends.server.config.ConfigEntry; import org.opends.server.config.ConfigException; import org.opends.server.core.DirectoryServer; import org.opends.server.types.ByteString; import org.opends.server.types.ErrorLogCategory; import org.opends.server.types.ErrorLogSeverity; import org.opends.server.types.DN; import org.opends.server.types.DebugLogLevel; import static org.opends.server.loggers.Error.*; import static org.opends.server.loggers.debug.DebugLogger.debugCaught; import static org.opends.server.loggers.debug.DebugLogger.debugEnabled; import static org.opends.server.messages.SchemaMessages.*; import static org.opends.server.schema.SchemaConstants.*; import org.opends.server.authorization.dseecompat.Aci; import org.opends.server.authorization.dseecompat.AciException; /** * This class implements the access control information (aci) attribute syntax. */ public class AciSyntax extends AttributeSyntax { // The default approximate matching rule for this syntax. private ApproximateMatchingRule defaultApproximateMatchingRule; // The default equality matching rule for this syntax. private EqualityMatchingRule defaultEqualityMatchingRule; // The default ordering matching rule for this syntax. private OrderingMatchingRule defaultOrderingMatchingRule; // The default substring matching rule for this syntax. private SubstringMatchingRule defaultSubstringMatchingRule; /** * Creates a new instance of this syntax. Note that the only thing that * should be done here is to invoke the default constructor for the * superclass. All initialization should be performed in the * <CODE>initializeSyntax</CODE> method. */ public AciSyntax() { super(); } /** * Initializes this attribute syntax based on the information in the provided * configuration entry. * * @param configEntry The configuration entry that contains the information * to use to initialize this attribute syntax. * * @throws ConfigException If an unrecoverable problem arises in the * process of performing the initialization. */ public void initializeSyntax(ConfigEntry configEntry) throws ConfigException { // We don't need an approximate matching rule. defaultApproximateMatchingRule = null; defaultEqualityMatchingRule = DirectoryServer.getEqualityMatchingRule(EMR_CASE_IGNORE_IA5_OID); if (defaultEqualityMatchingRule == null) { logError(ErrorLogCategory.SCHEMA, ErrorLogSeverity.SEVERE_ERROR, MSGID_ATTR_SYNTAX_UNKNOWN_EQUALITY_MATCHING_RULE, EMR_CASE_IGNORE_IA5_OID, SYNTAX_ACI_NAME); } // We don't need an ordering matching rule. defaultOrderingMatchingRule = null; defaultSubstringMatchingRule = DirectoryServer.getSubstringMatchingRule(SMR_CASE_IGNORE_IA5_OID); if (defaultSubstringMatchingRule == null) { logError(ErrorLogCategory.SCHEMA, ErrorLogSeverity.SEVERE_ERROR, MSGID_ATTR_SYNTAX_UNKNOWN_SUBSTRING_MATCHING_RULE, SMR_CASE_IGNORE_IA5_OID, SYNTAX_ACI_NAME); } } /** * Retrieves the common name for this attribute syntax. * * @return The common name for this attribute syntax. */ public String getSyntaxName() { return SYNTAX_ACI_NAME; } /** * Retrieves the OID for this attribute syntax. * * @return The OID for this attribute syntax. */ public String getOID() { return SYNTAX_ACI_OID; } /** * Retrieves a description for this attribute syntax. * * @return A description for this attribute syntax. */ public String getDescription() { return SYNTAX_ACI_DESCRIPTION; } /** * Retrieves the default equality matching rule that will be used for * attributes with this syntax. * * @return The default equality matching rule that will be used for * attributes with this syntax, or <CODE>null</CODE> if equality * matches will not be allowed for this type by default. */ public EqualityMatchingRule getEqualityMatchingRule() { return defaultEqualityMatchingRule; } /** * Retrieves the default ordering matching rule that will be used for * attributes with this syntax. * * @return The default ordering matching rule that will be used for * attributes with this syntax, or <CODE>null</CODE> if ordering * matches will not be allowed for this type by default. */ public OrderingMatchingRule getOrderingMatchingRule() { return defaultOrderingMatchingRule; } /** * Retrieves the default substring matching rule that will be used for * attributes with this syntax. * * @return The default substring matching rule that will be used for * attributes with this syntax, or <CODE>null</CODE> if substring * matches will not be allowed for this type by default. */ public SubstringMatchingRule getSubstringMatchingRule() { return defaultSubstringMatchingRule; } /** * Retrieves the default approximate matching rule that will be used for * attributes with this syntax. * * @return The default approximate matching rule that will be used for * attributes with this syntax, or <CODE>null</CODE> if approximate * matches will not be allowed for this type by default. */ public ApproximateMatchingRule getApproximateMatchingRule() { return defaultApproximateMatchingRule; } /** * Indicates whether the provided value is acceptable for use in an attribute * with this syntax. If it is not, then the reason may be appended to the * provided buffer. * * @param value The value for which to make the determination. * @param invalidReason The buffer to which the invalid reason should be * appended. * * @return <CODE>true</CODE> if the provided value is acceptable for use with * this syntax, or <CODE>false</CODE> if not. */ public boolean valueIsAcceptable(ByteString value, StringBuilder invalidReason) { try { Aci.decode(value, DN.nullDN()); } catch (AciException e) { if (debugEnabled()) { debugCaught(DebugLogLevel.ERROR, e); } logError(ErrorLogCategory.ACCESS_CONTROL, ErrorLogSeverity.SEVERE_WARNING, e.getMessage(), e.getMessageID()); invalidReason.append(e.getMessage()); return false; } return true; } } opends/src/server/org/opends/server/schema/SchemaConstants.java
@@ -811,6 +811,29 @@ /** * The OID for the aci attribute syntax. */ public static final String SYNTAX_ACI_OID = OID_OPENDS_SERVER_ATTRIBUTE_SYNTAX_BASE + ".4"; /** * The description for aci attribute syntax. */ public static final String SYNTAX_ACI_DESCRIPTION = "Sun-defined Access Control Information"; /** * The name for the aci attribute syntax. */ public static final String SYNTAX_ACI_NAME = "ds-syntax-dseecompat-aci"; /** * The description for the attribute type description attribute syntax. */ opends/tests/unit-tests-testng/src/server/org/opends/server/TestAccessLogger.java
@@ -260,7 +260,7 @@ addCommonRequestElements(addOperation, buffer); buffer.append(" dn=\""); buffer.append(addOperation.getRawEntryDN()); buffer.append("\" attibutes={"); buffer.append("\" attributes={"); Iterator<LDAPAttribute> attrIterator = addOperation.getRawAttributes().iterator();