001 /* 002 * Copyright 2008-2015 UnboundID Corp. 003 * All Rights Reserved. 004 */ 005 /* 006 * Copyright (C) 2015 UnboundID Corp. 007 * 008 * This program is free software; you can redistribute it and/or modify 009 * it under the terms of the GNU General Public License (GPLv2 only) 010 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 011 * as published by the Free Software Foundation. 012 * 013 * This program is distributed in the hope that it will be useful, 014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 016 * GNU General Public License for more details. 017 * 018 * You should have received a copy of the GNU General Public License 019 * along with this program; if not, see <http://www.gnu.org/licenses>. 020 */ 021 package com.unboundid.ldap.sdk.unboundidds.controls; 022 023 024 025 import java.util.ArrayList; 026 import java.util.Arrays; 027 import java.util.Collections; 028 import java.util.Iterator; 029 import java.util.List; 030 031 import com.unboundid.asn1.ASN1Boolean; 032 import com.unboundid.asn1.ASN1Element; 033 import com.unboundid.asn1.ASN1OctetString; 034 import com.unboundid.asn1.ASN1Sequence; 035 import com.unboundid.ldap.sdk.Control; 036 import com.unboundid.ldap.sdk.LDAPException; 037 import com.unboundid.ldap.sdk.ResultCode; 038 import com.unboundid.util.NotMutable; 039 import com.unboundid.util.ThreadSafety; 040 import com.unboundid.util.ThreadSafetyLevel; 041 042 import static com.unboundid.ldap.sdk.unboundidds.controls.ControlMessages.*; 043 import static com.unboundid.util.Debug.*; 044 import static com.unboundid.util.StaticUtils.*; 045 046 047 048 /** 049 * <BLOCKQUOTE> 050 * <B>NOTE:</B> This class is part of the Commercial Edition of the UnboundID 051 * LDAP SDK for Java. It is not available for use in applications that 052 * include only the Standard Edition of the LDAP SDK, and is not supported for 053 * use in conjunction with non-UnboundID products. 054 * </BLOCKQUOTE> 055 * This class provides an implementation of an LDAP control that can be included 056 * in a bind request to request that the Directory Server return the 057 * authentication and authorization entries for the user that authenticated. 058 * The value of this control may be absent, but if it is present then will be 059 * encoded as follows: 060 * <PRE> 061 * GetAuthorizationEntryRequest ::= SEQUENCE { 062 * includeAuthNEntry [0] BOOLEAN DEFAULT TRUE, 063 * includeAuthZEntry [1] BOOLEAN DEFAULT TRUE, 064 * attributes [2] AttributeSelection OPTIONAL } 065 * </PRE> 066 * <BR><BR> 067 * <H2>Example</H2> 068 * The following example demonstrates the process for processing a bind 069 * operation using the get authorization entry request control to return all 070 * user attributes in both the authentication and authorization entries: 071 * <PRE> 072 * ReadOnlyEntry authNEntry = null; 073 * ReadOnlyEntry authZEntry = null; 074 * 075 * BindRequest bindRequest = new SimpleBindRequest( 076 * "uid=john.doe,ou=People,dc=example,dc=com", "password", 077 * new GetAuthorizationEntryRequestControl()); 078 * 079 * BindResult bindResult = connection.bind(bindRequest); 080 * GetAuthorizationEntryResponseControl c = 081 * GetAuthorizationEntryResponseControl.get(bindResult); 082 * if (c != null) 083 * { 084 * authNEntry = c.getAuthNEntry(); 085 * authZEntry = c.getAuthZEntry(); 086 * } 087 * </PRE> 088 */ 089 @NotMutable() 090 @ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE) 091 public final class GetAuthorizationEntryRequestControl 092 extends Control 093 { 094 /** 095 * The OID (1.3.6.1.4.1.30221.2.5.6) for the get authorization entry request 096 * control. 097 */ 098 public static final String GET_AUTHORIZATION_ENTRY_REQUEST_OID = 099 "1.3.6.1.4.1.30221.2.5.6"; 100 101 102 103 /** 104 * The BER type for the {@code includeAuthNEntry} element. 105 */ 106 private static final byte TYPE_INCLUDE_AUTHN_ENTRY = (byte) 0x80; 107 108 109 110 /** 111 * The BER type for the {@code includeAuthZEntry} element. 112 */ 113 private static final byte TYPE_INCLUDE_AUTHZ_ENTRY = (byte) 0x81; 114 115 116 117 /** 118 * The BER type for the {@code attributes} element. 119 */ 120 private static final byte TYPE_ATTRIBUTES = (byte) 0xA2; 121 122 123 124 /** 125 * The serial version UID for this serializable class. 126 */ 127 private static final long serialVersionUID = -5540345171260624216L; 128 129 130 131 // Indicates whether to include the authentication entry in the response. 132 private final boolean includeAuthNEntry; 133 134 // Indicates whether to include the authorization entry in the response. 135 private final boolean includeAuthZEntry; 136 137 // The list of attributes to include in entries that are returned. 138 private final List<String> attributes; 139 140 141 142 /** 143 * Creates a new get authorization entry request control that will request all 144 * user attributes in both the authentication and authorization entries. It 145 * will not be marked critical. 146 */ 147 public GetAuthorizationEntryRequestControl() 148 { 149 this(false, true, true, (List<String>) null); 150 } 151 152 153 154 /** 155 * Creates a new get authorization entry request control with the provided 156 * information. 157 * 158 * @param includeAuthNEntry Indicates whether to include the authentication 159 * entry in the response. 160 * @param includeAuthZEntry Indicates whether to include the authorization 161 * entry in the response. 162 * @param attributes The attributes to include in the entries in the 163 * response. It may be empty or {@code null} to 164 * request all user attributes. 165 */ 166 public GetAuthorizationEntryRequestControl(final boolean includeAuthNEntry, 167 final boolean includeAuthZEntry, 168 final String... attributes) 169 { 170 this(false, includeAuthNEntry, includeAuthZEntry, 171 (attributes == null) ? null : Arrays.asList(attributes)); 172 } 173 174 175 176 /** 177 * Creates a new get authorization entry request control with the provided 178 * information. 179 * 180 * @param includeAuthNEntry Indicates whether to include the authentication 181 * entry in the response. 182 * @param includeAuthZEntry Indicates whether to include the authorization 183 * entry in the response. 184 * @param attributes The attributes to include in the entries in the 185 * response. It may be empty or {@code null} to 186 * request all user attributes. 187 */ 188 public GetAuthorizationEntryRequestControl(final boolean includeAuthNEntry, 189 final boolean includeAuthZEntry, 190 final List<String> attributes) 191 { 192 this(false, includeAuthNEntry, includeAuthZEntry, attributes); 193 } 194 195 196 197 /** 198 * Creates a new get authorization entry request control with the provided 199 * information. 200 * 201 * @param isCritical Indicates whether the control should be marked 202 * critical. 203 * @param includeAuthNEntry Indicates whether to include the authentication 204 * entry in the response. 205 * @param includeAuthZEntry Indicates whether to include the authorization 206 * entry in the response. 207 * @param attributes The attributes to include in the entries in the 208 * response. It may be empty or {@code null} to 209 * request all user attributes. 210 */ 211 public GetAuthorizationEntryRequestControl(final boolean isCritical, 212 final boolean includeAuthNEntry, 213 final boolean includeAuthZEntry, 214 final String... attributes) 215 { 216 this(isCritical, includeAuthNEntry, includeAuthZEntry, 217 (attributes == null) ? null : Arrays.asList(attributes)); 218 } 219 220 221 222 /** 223 * Creates a new get authorization entry request control with the provided 224 * information. 225 * 226 * @param isCritical Indicates whether the control should be marked 227 * critical. 228 * @param includeAuthNEntry Indicates whether to include the authentication 229 * entry in the response. 230 * @param includeAuthZEntry Indicates whether to include the authorization 231 * entry in the response. 232 * @param attributes The attributes to include in the entries in the 233 * response. It may be empty or {@code null} to 234 * request all user attributes. 235 */ 236 public GetAuthorizationEntryRequestControl(final boolean isCritical, 237 final boolean includeAuthNEntry, 238 final boolean includeAuthZEntry, 239 final List<String> attributes) 240 { 241 super(GET_AUTHORIZATION_ENTRY_REQUEST_OID, isCritical, 242 encodeValue(includeAuthNEntry, includeAuthZEntry, attributes)); 243 244 this.includeAuthNEntry = includeAuthNEntry; 245 this.includeAuthZEntry = includeAuthZEntry; 246 247 if ((attributes == null) || attributes.isEmpty()) 248 { 249 this.attributes = Collections.emptyList(); 250 } 251 else 252 { 253 this.attributes = 254 Collections.unmodifiableList(new ArrayList<String>(attributes)); 255 } 256 } 257 258 259 260 /** 261 * Creates a new get authorization entry request control which is decoded from 262 * the provided generic control. 263 * 264 * @param control The generic control to decode as a get authorization entry 265 * request control. 266 * 267 * @throws LDAPException If the provided control cannot be decoded as a get 268 * authorization entry request control. 269 */ 270 public GetAuthorizationEntryRequestControl(final Control control) 271 throws LDAPException 272 { 273 super(control); 274 275 final ASN1OctetString value = control.getValue(); 276 if (value == null) 277 { 278 includeAuthNEntry = true; 279 includeAuthZEntry = true; 280 attributes = Collections.emptyList(); 281 return; 282 } 283 284 try 285 { 286 final ArrayList<String> attrs = new ArrayList<String>(); 287 boolean includeAuthN = true; 288 boolean includeAuthZ = true; 289 290 final ASN1Element element = ASN1Element.decode(value.getValue()); 291 for (final ASN1Element e : 292 ASN1Sequence.decodeAsSequence(element).elements()) 293 { 294 switch (e.getType()) 295 { 296 case TYPE_INCLUDE_AUTHN_ENTRY: 297 includeAuthN = ASN1Boolean.decodeAsBoolean(e).booleanValue(); 298 break; 299 case TYPE_INCLUDE_AUTHZ_ENTRY: 300 includeAuthZ = ASN1Boolean.decodeAsBoolean(e).booleanValue(); 301 break; 302 case TYPE_ATTRIBUTES: 303 for (final ASN1Element ae : 304 ASN1Sequence.decodeAsSequence(e).elements()) 305 { 306 attrs.add(ASN1OctetString.decodeAsOctetString(ae).stringValue()); 307 } 308 break; 309 default: 310 throw new LDAPException(ResultCode.DECODING_ERROR, 311 ERR_GET_AUTHORIZATION_ENTRY_REQUEST_INVALID_SEQUENCE_ELEMENT. 312 get(toHex(e.getType()))); 313 } 314 } 315 316 includeAuthNEntry = includeAuthN; 317 includeAuthZEntry = includeAuthZ; 318 attributes = attrs; 319 } 320 catch (LDAPException le) 321 { 322 throw le; 323 } 324 catch (Exception e) 325 { 326 debugException(e); 327 throw new LDAPException(ResultCode.DECODING_ERROR, 328 ERR_GET_AUTHORIZATION_ENTRY_REQUEST_CANNOT_DECODE_VALUE.get( 329 getExceptionMessage(e)), e); 330 } 331 } 332 333 334 335 /** 336 * Encodes the provided information as appropriate for use as the value of 337 * this control. 338 * 339 * @param includeAuthNEntry Indicates whether to include the authentication 340 * entry in the response. 341 * @param includeAuthZEntry Indicates whether to include the authorization 342 * entry in the response. 343 * @param attributes The attributes to include in the entries in the 344 * response. It may be empty or {@code null} to 345 * request all user attributes. 346 * 347 * @return An ASN.1 octet string appropriately encoded for use as the control 348 * value, or {@code null} if no value is needed. 349 */ 350 private static ASN1OctetString encodeValue(final boolean includeAuthNEntry, 351 final boolean includeAuthZEntry, 352 final List<String> attributes) 353 { 354 if (includeAuthNEntry && includeAuthZEntry && 355 ((attributes == null) || attributes.isEmpty())) 356 { 357 return null; 358 } 359 360 final ArrayList<ASN1Element> elements = new ArrayList<ASN1Element>(3); 361 362 if (! includeAuthNEntry) 363 { 364 elements.add(new ASN1Boolean(TYPE_INCLUDE_AUTHN_ENTRY, false)); 365 } 366 367 if (! includeAuthZEntry) 368 { 369 elements.add(new ASN1Boolean(TYPE_INCLUDE_AUTHZ_ENTRY, false)); 370 } 371 372 if ((attributes != null) && (! attributes.isEmpty())) 373 { 374 final ArrayList<ASN1Element> attrElements = 375 new ArrayList<ASN1Element>(attributes.size()); 376 for (final String s : attributes) 377 { 378 attrElements.add(new ASN1OctetString(s)); 379 } 380 381 elements.add(new ASN1Sequence(TYPE_ATTRIBUTES, attrElements)); 382 } 383 384 return new ASN1OctetString(new ASN1Sequence(elements).encode()); 385 } 386 387 388 389 /** 390 * Indicates whether the entry for the authenticated user should be included 391 * in the response control. 392 * 393 * @return {@code true} if the entry for the authenticated user should be 394 * included in the response control, or {@code false} if not. 395 */ 396 public boolean includeAuthNEntry() 397 { 398 return includeAuthNEntry; 399 } 400 401 402 403 /** 404 * Indicates whether the entry for the authorized user should be included 405 * in the response control. 406 * 407 * @return {@code true} if the entry for the authorized user should be 408 * included in the response control, or {@code false} if not. 409 */ 410 public boolean includeAuthZEntry() 411 { 412 return includeAuthZEntry; 413 } 414 415 416 417 /** 418 * Retrieves the attributes that will be requested for the authentication 419 * and/or authorization entries. 420 * 421 * @return The attributes that will be requested for the authentication 422 * and/or authorization entries, or an empty list if all user 423 * attributes should be included. 424 */ 425 public List<String> getAttributes() 426 { 427 return attributes; 428 } 429 430 431 432 /** 433 * {@inheritDoc} 434 */ 435 @Override() 436 public String getControlName() 437 { 438 return INFO_CONTROL_NAME_GET_AUTHORIZATION_ENTRY_REQUEST.get(); 439 } 440 441 442 443 /** 444 * {@inheritDoc} 445 */ 446 @Override() 447 public void toString(final StringBuilder buffer) 448 { 449 buffer.append("GetAuthorizationEntryRequestControl(isCritical="); 450 buffer.append(isCritical()); 451 buffer.append(", includeAuthNEntry="); 452 buffer.append(includeAuthNEntry); 453 buffer.append(", includeAuthZEntry="); 454 buffer.append(includeAuthZEntry); 455 buffer.append(", attributes={"); 456 457 final Iterator<String> iterator = attributes.iterator(); 458 while (iterator.hasNext()) 459 { 460 buffer.append(iterator.next()); 461 if (iterator.hasNext()) 462 { 463 buffer.append(", "); 464 } 465 } 466 467 buffer.append("})"); 468 } 469 }