001 /*
002 * CDDL HEADER START
003 *
004 * The contents of this file are subject to the terms of the
005 * Common Development and Distribution License, Version 1.0 only
006 * (the "License"). You may not use this file except in compliance
007 * with the License.
008 *
009 * You can obtain a copy of the license at
010 * trunk/opends/resource/legal-notices/OpenDS.LICENSE
011 * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
012 * See the License for the specific language governing permissions
013 * and limitations under the License.
014 *
015 * When distributing Covered Code, include this CDDL HEADER in each
016 * file and include the License file at
017 * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
018 * add the following below this CDDL HEADER, with the fields enclosed
019 * by brackets "[]" replaced with your own identifying information:
020 * Portions Copyright [yyyy] [name of copyright owner]
021 *
022 * CDDL HEADER END
023 *
024 *
025 * Copyright 2008 Sun Microsystems, Inc.
026 */
027
028 package org.opends.server.controls;
029 import org.opends.messages.Message;
030
031 import org.opends.server.types.*;
032 import org.opends.server.protocols.asn1.ASN1OctetString;
033 import org.opends.server.protocols.asn1.ASN1Element;
034 import org.opends.server.protocols.asn1.ASN1Exception;
035 import org.opends.server.protocols.ldap.LDAPResultCode;
036 import static org.opends.server.util.ServerConstants.OID_GET_EFFECTIVE_RIGHTS;
037 import static org.opends.server.util.Validator.ensureNotNull;
038 import static org.opends.server.util.StaticUtils.toLowerCase;
039 import org.opends.server.core.DirectoryServer;
040 import static org.opends.messages.ProtocolMessages.*;
041 import static org.opends.server.loggers.debug.DebugLogger.*;
042 import org.opends.server.loggers.debug.DebugTracer;
043
044 import java.util.List;
045 import java.util.ArrayList;
046 import java.util.LinkedList;
047
048 /**
049 * This class partially implements the geteffectiverights control as defined
050 * in draft-ietf-ldapext-acl-model-08.txt. The main differences are:
051 *
052 * - The response control is not supported. Instead the dseecompat
053 * geteffectiverights control implementation creates attributes containing
054 * right information strings and adds those attributes to the
055 * entry being returned. The attribute type names are dynamically created;
056 * see the dseecompat's AciGetEffectiveRights class for details.
057 *
058 * - The dseecompat implementation allows additional attribute types
059 * in the request control for which rights information can be returned.
060 * These are known as the specified attribute types.
061 *
062 * The dseecompat request control value is the following:
063 *
064 * <BR>
065 * <PRE>
066 * GetRightsControl ::= SEQUENCE {
067 * authzId authzId
068 * attributes SEQUENCE OF AttributeType
069 * }
070 *
071 * -- Only the "dn:DN form is supported.
072 *
073 * </PRE>
074 *
075 **/
076 public class GetEffectiveRights extends Control {
077 /**
078 * The tracer object for the debug logger.
079 */
080 private static final DebugTracer TRACER = getTracer();
081
082
083 //The DN representing the authzId. May be null.
084 private DN authzDN=null;
085
086 //The list of additional attribute types to return rights for. May be null.
087 private List<AttributeType> attrs=null;
088
089 /**
090 * Create a new geteffectiverights control with null authzDN and null
091 * attribute list.
092 */
093 public GetEffectiveRights() {
094 super(OID_GET_EFFECTIVE_RIGHTS, true, null);
095 }
096
097 /**
098 * Create a new geteffectiverights control with the specified raw octet
099 * string, an authzDN and an attribute list.
100 *
101 * @param val The octet string repsentation of the control value.
102 *
103 * @param authzDN The authzDN.
104 *
105 * @param attrs The list of additional attributes to be returned.
106 */
107 public GetEffectiveRights(ASN1OctetString val, DN authzDN,
108 List<AttributeType> attrs) {
109 super(OID_GET_EFFECTIVE_RIGHTS, true, val);
110 this.authzDN=authzDN;
111 this.attrs=attrs;
112 }
113
114 /**
115 * Return the authzDN parsed from the control.
116 *
117 * @return The DN representing the authzId.
118 */
119 public DN getAuthzDN () {
120 return authzDN;
121 }
122
123 /**
124 * Return the requested additional attributes parsed from the control. Known
125 * as the specified attributes.
126 *
127 * @return The list containing any additional attributes to return rights
128 * about.
129 */
130 public List<AttributeType> getAttributes() {
131 return attrs;
132 }
133
134
135 /**
136 * Decodes the provided ASN1 element. Assume that it is a ASN1 sequence
137 * of attributetypes.
138 *
139 * @param attributeElement The ASN1 element to be decoded.
140 *
141 * @return A list of attribute types to process rights of.
142 *
143 * @throws ASN1Exception If the attribute element cannot be decoded as a
144 * sequence.
145 */
146 private static
147 List<AttributeType> decodeAttributeSequence(ASN1Element attributeElement)
148 throws ASN1Exception {
149 List<AttributeType> attributeList = new LinkedList<AttributeType>();
150 //Decode the sequence element and put the individual elements in array.
151 ArrayList<ASN1Element> attrElems =
152 attributeElement.decodeAsSequence().elements();
153 int numAttrElements = attrElems.size();
154 for(int i=0; i < numAttrElements; i++) {
155 //Decode as an octet string.
156 ASN1OctetString tmp=attrElems.get(i).decodeAsOctetString();
157 //Get an attribute type for it and add to the list.
158 AttributeType attributeType;
159 if((attributeType =
160 DirectoryServer.getAttributeType(tmp.toString())) == null)
161 attributeType =
162 DirectoryServer.getDefaultAttributeType(tmp.toString());
163 attributeList.add(attributeType);
164 }
165 return attributeList;
166 }
167
168 /**
169 * Decodes the request control's value octet string into a GetEffectiveRights
170 * class. It assumes that it is an ASN1 sequence as described in class
171 * description.
172 *
173 * @param val The octet string repsentation of the control value.
174 *
175 * @return A decoded GetEffectiveRights class representing the request
176 * control.
177 *
178 * @throws LDAPException If the request control's value contains errors
179 * causing a valid GetEffectiveRights class to not
180 * be created.
181 */
182 private static
183 GetEffectiveRights decodeValueSequence(ASN1OctetString val )
184 throws LDAPException {
185 DN authzDN;
186 List<AttributeType> attrs=null;
187 String authzIDString="";
188 try {
189 ASN1Element sequence = ASN1Element.decode(val.value());
190 ArrayList<ASN1Element> elements =
191 sequence.decodeAsSequence().elements();
192 ASN1OctetString authzID = elements.get(0).decodeAsOctetString();
193 //There is an sequence containing an attribute list, try to decode it.
194 if(elements.size() == 2)
195 attrs=decodeAttributeSequence(elements.get(1));
196 authzIDString = authzID.stringValue();
197 String lowerAuthzIDString = toLowerCase(authzIDString);
198 //Make sure authzId starts with "dn:" and is a valid DN.
199 if (lowerAuthzIDString.startsWith("dn:"))
200 authzDN = DN.decode(authzIDString.substring(3));
201 else {
202 Message message = INFO_GETEFFECTIVERIGHTS_INVALID_AUTHZID.get(
203 String.valueOf(authzID));
204 throw new LDAPException(LDAPResultCode.PROTOCOL_ERROR, message);
205 }
206 } catch (ASN1Exception e) {
207 if (debugEnabled()) {
208 TRACER.debugCaught(DebugLogLevel.ERROR, e);
209 }
210
211 Message message =
212 INFO_GETEFFECTIVERIGHTS_DECODE_ERROR.get(e.getMessage());
213 throw new LDAPException(LDAPResultCode.PROTOCOL_ERROR, message);
214 } catch (DirectoryException de) {
215 if (debugEnabled()) {
216 TRACER.debugCaught(DebugLogLevel.ERROR, de);
217 }
218
219 Message message = INFO_CANNOT_DECODE_GETEFFECTIVERIGHTS_AUTHZID_DN.get(
220 authzIDString.substring(3), de.getMessageObject());
221 throw new LDAPException(LDAPResultCode.PROTOCOL_ERROR, message);
222 }
223 return new GetEffectiveRights(val, authzDN, attrs);
224 }
225
226 /**
227 * Decodes the request control's value into a GetEffectiveRights class.
228 *
229 * @param control The control class representing the request control.
230 *
231 * @return A decoded GetEffectiveRights class representing the request
232 * control.
233 *
234 * @throws LDAPException If the request control's value contains errors
235 * causing a valid GetEffectiveRights class to not
236 * be created.
237 */
238 public static
239 GetEffectiveRights decodeControl(Control control) throws LDAPException {
240 ensureNotNull(control);
241 ASN1OctetString value=control.getValue();
242 //If the value is null create a GetEffectiveRights class with null
243 //authzDN and attribute list, else try to decode the value.
244 if(value == null)
245 return new GetEffectiveRights();
246 else
247 return GetEffectiveRights.decodeValueSequence(value);
248 }
249 }