001/* 002 * The contents of this file are subject to the terms of the Common Development and 003 * Distribution License (the License). You may not use this file except in compliance with the 004 * License. 005 * 006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the 007 * specific language governing permission and limitations under the License. 008 * 009 * When distributing Covered Software, include this CDDL Header Notice in each file and include 010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL 011 * Header, with the fields enclosed by brackets [] replaced by your own identifying 012 * information: "Portions Copyright [year] [name of copyright owner]". 013 * 014 * Copyright 2009 Sun Microsystems, Inc. 015 * Portions Copyright 2014-2016 ForgeRock AS. 016 */ 017package org.opends.server.controls; 018 019import java.io.IOException; 020import java.util.LinkedList; 021import java.util.List; 022 023import org.forgerock.i18n.LocalizableMessage; 024import org.forgerock.i18n.slf4j.LocalizedLogger; 025import org.forgerock.opendj.io.ASN1; 026import org.forgerock.opendj.io.ASN1Reader; 027import org.forgerock.opendj.io.ASN1Writer; 028import org.forgerock.opendj.ldap.ByteString; 029import org.forgerock.opendj.ldap.ResultCode; 030import org.forgerock.opendj.ldap.schema.AttributeType; 031import org.opends.server.core.DirectoryServer; 032import org.opends.server.types.Control; 033import org.forgerock.opendj.ldap.DN; 034import org.opends.server.types.DirectoryException; 035 036import static org.opends.messages.ProtocolMessages.*; 037import static org.opends.server.util.ServerConstants.*; 038 039/** 040 * This class partially implements the geteffectiverights control as defined 041 * in draft-ietf-ldapext-acl-model-08.txt. The main differences are: 042 * 043 * - The response control is not supported. Instead the dseecompat 044 * geteffectiverights control implementation creates attributes containing 045 * right information strings and adds those attributes to the 046 * entry being returned. The attribute type names are dynamically created; 047 * see the dseecompat's AciGetEffectiveRights class for details. 048 * 049 * - The dseecompat implementation allows additional attribute types 050 * in the request control for which rights information can be returned. 051 * These are known as the specified attribute types. 052 * 053 * The dseecompat request control value is the following: 054 * 055 * <BR> 056 * <PRE> 057 * GetRightsControl ::= SEQUENCE { 058 * authzId authzId 059 * attributes SEQUENCE OF AttributeType 060 * } 061 * 062 * -- Only the "dn:DN form is supported. 063 * 064 * </PRE> 065 * 066 **/ 067public class GetEffectiveRightsRequestControl extends Control 068{ 069 /** 070 * ControlDecoder implementation to decode this control from a ByteString. 071 */ 072 private static final class Decoder 073 implements ControlDecoder<GetEffectiveRightsRequestControl> 074 { 075 @Override 076 public GetEffectiveRightsRequestControl decode(boolean isCritical, 077 ByteString value) throws DirectoryException 078 { 079 // If the value is null create a GetEffectiveRightsRequestControl 080 // class with null authzDN and attribute list, else try to 081 // decode the value. 082 if (value == null) 083 { 084 return new GetEffectiveRightsRequestControl(isCritical, (DN)null, 085 (List<AttributeType>)null); 086 } 087 else 088 { 089 ASN1Reader reader = ASN1.getReader(value); 090 DN authzDN; 091 List<AttributeType> attrs=null; 092 String authzIDString=""; 093 try { 094 reader.readStartSequence(); 095 authzIDString = reader.readOctetStringAsString(); 096 String lowerAuthzIDString = authzIDString.toLowerCase(); 097 //Make sure authzId starts with "dn:" and is a valid DN. 098 if (lowerAuthzIDString.startsWith("dn:")) 099 { 100 authzDN = DN.valueOf(authzIDString.substring(3)); 101 } 102 else { 103 LocalizableMessage message = INFO_GETEFFECTIVERIGHTS_INVALID_AUTHZID.get( 104 lowerAuthzIDString); 105 throw new DirectoryException(ResultCode.PROTOCOL_ERROR, message); 106 } 107 //There is an sequence containing an attribute list, try to decode it. 108 if(reader.hasNextElement()) { 109 attrs = new LinkedList<>(); 110 reader.readStartSequence(); 111 while(reader.hasNextElement()) { 112 String attrStr = reader.readOctetStringAsString(); 113 attrs.add(DirectoryServer.getSchema().getAttributeType(attrStr)); 114 } 115 reader.readEndSequence(); 116 } 117 reader.readEndSequence(); 118 } catch (IOException e) { 119 logger.traceException(e); 120 121 LocalizableMessage message = 122 INFO_GETEFFECTIVERIGHTS_DECODE_ERROR.get(e.getMessage()); 123 throw new DirectoryException(ResultCode.PROTOCOL_ERROR, message); 124 } 125 126 return new GetEffectiveRightsRequestControl(isCritical, 127 authzDN, attrs); 128 } 129 } 130 131 @Override 132 public String getOID() 133 { 134 return OID_GET_EFFECTIVE_RIGHTS; 135 } 136 } 137 138 /** 139 * The Control Decoder that can be used to decode this control. 140 */ 141 public static final ControlDecoder<GetEffectiveRightsRequestControl> DECODER = 142 new Decoder(); 143 private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); 144 145 /** The DN representing the authzId. May be null. */ 146 private DN authzDN; 147 148 /** The raw DN representing the authzId. May be null. */ 149 private String rawAuthzDN; 150 151 /** The list of additional attribute types to return rights for. May be null. */ 152 private List<AttributeType> attrs; 153 154 /** The raw DN representing the authzId. May be null. */ 155 private List<String> rawAttrs; 156 157 /** 158 * Create a new geteffectiverights control with the specified authzDN and 159 * an attribute list. 160 * 161 * @param authzDN The authzDN. 162 * 163 * @param attrs The list of additional attributes to be returned. 164 */ 165 public GetEffectiveRightsRequestControl(DN authzDN, 166 List<AttributeType> attrs) { 167 this(true, authzDN, attrs); 168 } 169 170 /** 171 * Create a new geteffectiverights control with the specified authzDN and 172 * an attribute list. 173 * 174 * @param isCritical Indicates whether this control should be 175 * considered critical in processing the 176 * request. 177 * @param authzDN The authzDN. 178 * @param attrs The list of additional attributes to be returned. 179 */ 180 public GetEffectiveRightsRequestControl(boolean isCritical, DN authzDN, 181 List<AttributeType> attrs) { 182 super(OID_GET_EFFECTIVE_RIGHTS, isCritical); 183 this.authzDN=authzDN; 184 this.attrs=attrs; 185 } 186 187 /** 188 * Create a new geteffectiverights control with the specified raw 189 * authzDN and an attribute list. 190 * 191 * @param isCritical Indicates whether this control should be 192 * considered critical in processing the 193 * request. 194 * @param authzDN The authzDN. 195 * @param attrs The list of additional attributes to be returned. 196 */ 197 public GetEffectiveRightsRequestControl(boolean isCritical, 198 String authzDN, 199 List<String> attrs) 200 { 201 super(OID_GET_EFFECTIVE_RIGHTS, isCritical); 202 this.rawAuthzDN=authzDN; 203 this.rawAttrs=attrs; 204 } 205 206 @Override 207 public void writeValue(ASN1Writer writer) throws IOException { 208 writer.writeStartSequence(ASN1.UNIVERSAL_OCTET_STRING_TYPE); 209 210 writer.writeStartSequence(); 211 if(authzDN != null) 212 { 213 writer.writeOctetString("dn:" + authzDN); 214 } 215 else if(rawAuthzDN != null) 216 { 217 writer.writeOctetString("dn:" + rawAuthzDN); 218 } 219 220 if(attrs != null) 221 { 222 writer.writeStartSequence(); 223 for(AttributeType attr : attrs) 224 { 225 writer.writeOctetString(attr.getNameOrOID()); 226 } 227 writer.writeEndSequence(); 228 } 229 else if(rawAttrs != null) 230 { 231 writer.writeStartSequence(); 232 for(String attr : rawAttrs) 233 { 234 writer.writeOctetString(attr); 235 } 236 writer.writeEndSequence(); 237 } 238 writer.writeEndSequence(); 239 240 writer.writeEndSequence(); 241 } 242 243 /** 244 * Return the authzDN parsed from the control. 245 * 246 * @return The DN representing the authzId. 247 */ 248 public DN getAuthzDN () { 249 return authzDN; 250 // TODO: what if rawAuthzDN is not null? 251 } 252 253 /** 254 * Return the requested additional attributes parsed from the control. Known 255 * as the specified attributes. 256 * 257 * @return The list containing any additional attributes to return rights 258 * about. 259 */ 260 public List<AttributeType> getAttributes() { 261 return attrs; 262 } 263}