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 }