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 }