/*
* 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.controls;
import org.opends.messages.Message;
import org.opends.server.types.*;
import org.opends.server.protocols.asn1.ASN1OctetString;
import org.opends.server.protocols.asn1.ASN1Element;
import org.opends.server.protocols.asn1.ASN1Exception;
import org.opends.server.protocols.ldap.LDAPResultCode;
import static org.opends.server.util.ServerConstants.OID_GET_EFFECTIVE_RIGHTS;
import static org.opends.server.util.Validator.ensureNotNull;
import static org.opends.server.util.StaticUtils.toLowerCase;
import org.opends.server.core.DirectoryServer;
import static org.opends.messages.ProtocolMessages.*;
import static org.opends.server.loggers.debug.DebugLogger.*;
import org.opends.server.loggers.debug.DebugTracer;
import java.util.List;
import java.util.ArrayList;
import java.util.LinkedList;
/**
* This class partially implements the geteffectiverights control as defined
* in draft-ietf-ldapext-acl-model-08.txt. The main differences are:
*
* - The response control is not supported. Instead the dseecompat
* geteffectiverights control implementation creates attributes containing
* right information strings and adds those attributes to the
* entry being returned. The attribute type names are dynamically created;
* see the dseecompat's AciGetEffectiveRights class for details.
*
* - The dseecompat implementation allows additional attribute types
* in the request control for which rights information can be returned.
* These are known as the specified attribute types.
*
* The dseecompat request control value is the following:
*
*
*
* GetRightsControl ::= SEQUENCE {
* authzId authzId
* attributes SEQUENCE OF AttributeType
* }
*
* -- Only the "dn:DN form is supported.
*
*
*
**/
public class GetEffectiveRights extends Control {
/**
* The tracer object for the debug logger.
*/
private static final DebugTracer TRACER = getTracer();
//The DN representing the authzId. May be null.
private DN authzDN=null;
//The list of additional attribute types to return rights for. May be null.
private List attrs=null;
/**
* Create a new geteffectiverights control with null authzDN and null
* attribute list.
*/
public GetEffectiveRights() {
super(OID_GET_EFFECTIVE_RIGHTS, true, null);
}
/**
* Create a new geteffectiverights control with the specified raw octet
* string, an authzDN and an attribute list.
*
* @param val The octet string repsentation of the control value.
*
* @param authzDN The authzDN.
*
* @param attrs The list of additional attributes to be returned.
*/
public GetEffectiveRights(ASN1OctetString val, DN authzDN,
List attrs) {
super(OID_GET_EFFECTIVE_RIGHTS, true, val);
this.authzDN=authzDN;
this.attrs=attrs;
}
/**
* Return the authzDN parsed from the control.
*
* @return The DN representing the authzId.
*/
public DN getAuthzDN () {
return authzDN;
}
/**
* Return the requested additional attributes parsed from the control. Known
* as the specified attributes.
*
* @return The list containing any additional attributes to return rights
* about.
*/
public List getAttributes() {
return attrs;
}
/**
* Decodes the provided ASN1 element. Assume that it is a ASN1 sequence
* of attributetypes.
*
* @param attributeElement The ASN1 element to be decoded.
*
* @return A list of attribute types to process rights of.
*
* @throws ASN1Exception If the attribute element cannot be decoded as a
* sequence.
*/
private static
List decodeAttributeSequence(ASN1Element attributeElement)
throws ASN1Exception {
List attributeList = new LinkedList();
//Decode the sequence element and put the individual elements in array.
ArrayList attrElems =
attributeElement.decodeAsSequence().elements();
int numAttrElements = attrElems.size();
for(int i=0; i < numAttrElements; i++) {
//Decode as an octet string.
ASN1OctetString tmp=attrElems.get(i).decodeAsOctetString();
//Get an attribute type for it and add to the list.
AttributeType attributeType;
if((attributeType =
DirectoryServer.getAttributeType(tmp.toString())) == null)
attributeType =
DirectoryServer.getDefaultAttributeType(tmp.toString());
attributeList.add(attributeType);
}
return attributeList;
}
/**
* Decodes the request control's value octet string into a GetEffectiveRights
* class. It assumes that it is an ASN1 sequence as described in class
* description.
*
* @param val The octet string repsentation of the control value.
*
* @return A decoded GetEffectiveRights class representing the request
* control.
*
* @throws LDAPException If the request control's value contains errors
* causing a valid GetEffectiveRights class to not
* be created.
*/
private static
GetEffectiveRights decodeValueSequence(ASN1OctetString val )
throws LDAPException {
DN authzDN;
List attrs=null;
String authzIDString="";
try {
ASN1Element sequence = ASN1Element.decode(val.value());
ArrayList elements =
sequence.decodeAsSequence().elements();
ASN1OctetString authzID = elements.get(0).decodeAsOctetString();
//There is an sequence containing an attribute list, try to decode it.
if(elements.size() == 2)
attrs=decodeAttributeSequence(elements.get(1));
authzIDString = authzID.stringValue();
String lowerAuthzIDString = toLowerCase(authzIDString);
//Make sure authzId starts with "dn:" and is a valid DN.
if (lowerAuthzIDString.startsWith("dn:"))
authzDN = DN.decode(authzIDString.substring(3));
else {
Message message = INFO_GETEFFECTIVERIGHTS_INVALID_AUTHZID.get(
String.valueOf(authzID));
throw new LDAPException(LDAPResultCode.PROTOCOL_ERROR, message);
}
} catch (ASN1Exception e) {
if (debugEnabled()) {
TRACER.debugCaught(DebugLogLevel.ERROR, e);
}
Message message =
INFO_GETEFFECTIVERIGHTS_DECODE_ERROR.get(e.getMessage());
throw new LDAPException(LDAPResultCode.PROTOCOL_ERROR, message);
} catch (DirectoryException de) {
if (debugEnabled()) {
TRACER.debugCaught(DebugLogLevel.ERROR, de);
}
Message message = INFO_CANNOT_DECODE_GETEFFECTIVERIGHTS_AUTHZID_DN.get(
authzIDString.substring(3), de.getMessageObject());
throw new LDAPException(LDAPResultCode.PROTOCOL_ERROR, message);
}
return new GetEffectiveRights(val, authzDN, attrs);
}
/**
* Decodes the request control's value into a GetEffectiveRights class.
*
* @param control The control class representing the request control.
*
* @return A decoded GetEffectiveRights class representing the request
* control.
*
* @throws LDAPException If the request control's value contains errors
* causing a valid GetEffectiveRights class to not
* be created.
*/
public static
GetEffectiveRights decodeControl(Control control) throws LDAPException {
ensureNotNull(control);
ASN1OctetString value=control.getValue();
//If the value is null create a GetEffectiveRights class with null
//authzDN and attribute list, else try to decode the value.
if(value == null)
return new GetEffectiveRights();
else
return GetEffectiveRights.decodeValueSequence(value);
}
}